如何在加入 table 时仅 SELECT 一行有重复的外键值?
How to SELECT only one row when joined table have duplicated foreign key value?
我怎么能SELECT在这个例子中只有一行(值),而在连接的table一列中外键有重复值?例如:
CREATE TABLE customers(
id INT (10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR (50) NOT NULL,
city VARCHAR (50) NOT NULL
);
CREATE TABLE orders(
cus_id INT (10) NOT NULL,
order_date DATETIME NOT NULL
);
CREATE TABLE products(
id INT (5) NOT NULL PRIMARY KEY,
product_name VARCHAR(50) NOT NULL,
product_price INT(10) NOT NULL
);
CREATE TABLE ordered_items(
id INT (10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
cus_id INT (10) NOT NULL,
product_id INT(5) NOT NULL
);
ALTER TABLE orders ADD CONSTRAINT customers_id_fr FOREIGN KEY ( cus_id ) REFERENCES customers ( id );
ALTER TABLE ordered_items ADD CONSTRAINT ordered_items_fr FOREIGN KEY ( cus_id ) REFERENCES customers ( id );
INSERT INTO customers (name, city) VALUES ("My Name", "New York");
INSERT INTO orders (cus_id, order_date) VALUES ("1", NOW());
INSERT INTO products (id, product_name, product_price) VALUES ("99", "My test product nr. 1", "20");
INSERT INTO products (id, product_name, product_price) VALUES ("98", "My test product nr. 2", "10");
INSERT INTO ordered_items (id, cus_id, product_id) VALUES ("1", "1", "99");
INSERT INTO ordered_items (id, cus_id, product_id) VALUES ("2", "1", "98");
SELECT name FROM customers INNER JOIN orders ON orders.cus_id = customers.id
INNER JOIN ordered_items ON ordered_items.cus_id = orders.cus_id
INNER JOIN products ON products.id = ordered_items.product_id;
在此示例中,结果将有两行具有相同的值。因为在 ordered_items table 中,我对同一个客户 ID 有两个值。
+=========+
| name |
+=========+
| My Name |
+---------+
| My Name |
+---------+
或者只是 SELECT DISCINT 会是解决方案吗?谢谢!
SELECT name -- Now... If a customer name could duplicate... that's a different problem in the data.
FROM customers
WHERE EXISTS (SELECT 1
FROM orders
INNER JOIN ordered_items ON ordered_items.cus_id = orders.cus_id
INNER JOIN products ON products.id = ordered_items.product_id
WHERE orders.cus_id = customers.id)
为什么?
简单地说:避免拉入 data/tables 你不需要。
如果您只需要来自客户 table 的名称并且不需要来自其他 table 的值,请在您的 where 子句中使用 EXISTS 语句;不要加入。连接是导致您出现问题的原因,您不需要它。通过从连接中消除不需要的 tables,您就消除了问题。当您需要来自被加入的 table 的字段时,可以使用加入。 Exists in your where 子句将在找到实例后提前退出。它可以使用索引并且应该稍微快一些,因为它不必查询 table 并加入所有 fields/rows。如果您需要来自其他 table 的值,那么 distinct 就是您的答案。如果你不能使用 distinct 因为你只想要 1 行 Lateral apply/Cross Apply 和 TOP 1 with order by 应该这样做。我不确定为什么您甚至让其他 table 只涉及客户,而 ordered_items 正是您所需要的,对吗?还是您没有告诉我们其他领域?
现在,当您添加其他字段时,它们可能会导致客户名称根据这些值进行复制:所以 GROUP BY
可能就是您所需要的。那么...您尝试通过此查询回答的“业务问题”是什么?
如果您真正追求的是已经下单的客户:
SELECT name
FROM customers
WHERE EXISTS (SELECT 1
FROM ordered_items ON ordered_items.cus_id = Customers.id
WHERE orders.cus_id = customers.id)
如上面评论中所述,在 customers.id
处使用 GROUP BY
语句
我怎么能SELECT在这个例子中只有一行(值),而在连接的table一列中外键有重复值?例如:
CREATE TABLE customers(
id INT (10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR (50) NOT NULL,
city VARCHAR (50) NOT NULL
);
CREATE TABLE orders(
cus_id INT (10) NOT NULL,
order_date DATETIME NOT NULL
);
CREATE TABLE products(
id INT (5) NOT NULL PRIMARY KEY,
product_name VARCHAR(50) NOT NULL,
product_price INT(10) NOT NULL
);
CREATE TABLE ordered_items(
id INT (10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
cus_id INT (10) NOT NULL,
product_id INT(5) NOT NULL
);
ALTER TABLE orders ADD CONSTRAINT customers_id_fr FOREIGN KEY ( cus_id ) REFERENCES customers ( id );
ALTER TABLE ordered_items ADD CONSTRAINT ordered_items_fr FOREIGN KEY ( cus_id ) REFERENCES customers ( id );
INSERT INTO customers (name, city) VALUES ("My Name", "New York");
INSERT INTO orders (cus_id, order_date) VALUES ("1", NOW());
INSERT INTO products (id, product_name, product_price) VALUES ("99", "My test product nr. 1", "20");
INSERT INTO products (id, product_name, product_price) VALUES ("98", "My test product nr. 2", "10");
INSERT INTO ordered_items (id, cus_id, product_id) VALUES ("1", "1", "99");
INSERT INTO ordered_items (id, cus_id, product_id) VALUES ("2", "1", "98");
SELECT name FROM customers INNER JOIN orders ON orders.cus_id = customers.id
INNER JOIN ordered_items ON ordered_items.cus_id = orders.cus_id
INNER JOIN products ON products.id = ordered_items.product_id;
在此示例中,结果将有两行具有相同的值。因为在 ordered_items table 中,我对同一个客户 ID 有两个值。
+=========+
| name |
+=========+
| My Name |
+---------+
| My Name |
+---------+
或者只是 SELECT DISCINT 会是解决方案吗?谢谢!
SELECT name -- Now... If a customer name could duplicate... that's a different problem in the data.
FROM customers
WHERE EXISTS (SELECT 1
FROM orders
INNER JOIN ordered_items ON ordered_items.cus_id = orders.cus_id
INNER JOIN products ON products.id = ordered_items.product_id
WHERE orders.cus_id = customers.id)
为什么?
简单地说:避免拉入 data/tables 你不需要。
如果您只需要来自客户 table 的名称并且不需要来自其他 table 的值,请在您的 where 子句中使用 EXISTS 语句;不要加入。连接是导致您出现问题的原因,您不需要它。通过从连接中消除不需要的 tables,您就消除了问题。当您需要来自被加入的 table 的字段时,可以使用加入。 Exists in your where 子句将在找到实例后提前退出。它可以使用索引并且应该稍微快一些,因为它不必查询 table 并加入所有 fields/rows。如果您需要来自其他 table 的值,那么 distinct 就是您的答案。如果你不能使用 distinct 因为你只想要 1 行 Lateral apply/Cross Apply 和 TOP 1 with order by 应该这样做。我不确定为什么您甚至让其他 table 只涉及客户,而 ordered_items 正是您所需要的,对吗?还是您没有告诉我们其他领域?
现在,当您添加其他字段时,它们可能会导致客户名称根据这些值进行复制:所以 GROUP BY
可能就是您所需要的。那么...您尝试通过此查询回答的“业务问题”是什么?
如果您真正追求的是已经下单的客户:
SELECT name
FROM customers
WHERE EXISTS (SELECT 1
FROM ordered_items ON ordered_items.cus_id = Customers.id
WHERE orders.cus_id = customers.id)
如上面评论中所述,在 customers.id
GROUP BY
语句