如何在加入 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 会是解决方案吗?谢谢!

Working example

Demo

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 可能就是您所需要的。那么...您尝试通过此查询回答的“业务问题”是什么?

如果您真正追求的是已经下单的客户:

Demo

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 语句

想看就看这里:https://www.w3schools.com/sql/sql_groupby.asp