我有桌子:
TABLE | COLUMNS
----------+----------------------------------
CUSTOMER | C_ID, C_NAME, C_ADDRESS
SHOP | S_ID, S_NAME, S_ADDRESS, S_COMPANY
ORDER | S_ID, C_ID, O_DATE
我想选择只从一家公司的商店订购的所有客户的ID - '三星'('LG','HP',......并不重要,它是动态的。)
我只有一个解决方案,但我觉得它很难看:
( SELECT DISTINCT c_id FROM order JOIN shop USING(s_id) WHERE s_company = "Samsung" )
EXCEPT
( SELECT DISTINCT c_id FROM order JOIN shop USING(s_id) WHERE s_company != "Samsung" );
相同的SQL查询,但反向运算符。是否有更好的解决此类查询的聚合方法?
我的意思是,可能有数百万的订单(我真的没有订单,我有更多经常发生的事情)。
选择数千个订单然后将它们与成千上万个订单进行比较是否有效?我知道,它比较了排序的东西,所以它是O( m + n + sort(n) + sort(m) )
。但对于数百万条记录而言,这仍然很大,或者不是?
还有一个问题。如何选择所有客户值(名称,地址)。我怎样才能加入他们,我能做到吗
SELECT CUSTOMER.* FROM CUSTOMER JOIN ( (SELECT...) EXCEPT (SELECT...) ) USING (C_ID);
免责声明:这个问题不是作业。它为考试做准备,并希望事情更有效。我的解决方案将在考试中被接受,但我喜欢有效的编程。
答案 0 :(得分:4)
我喜欢使用group by
和having
子句来处理此类问题。您可以使用以下方式获取客户列表:
select o.c_id
from orders o join
shops s
on o.s_id = o.s_id
group by c_id
having min(s.s_company) = max(s.s_company);
如果您关心特定公司,那么:
having min(s.s_company) = max(s.s_company) and
max(s.s_company) = 'Samsung'
如果您需要完整的客户信息,可以重新加入客户表。
这是否比except
版本效果更好,必须在您的系统上进行测试。
答案 1 :(得分:1)
不使用像Min和Max这样的聚合函数的查询怎么样?
select C_ID, S_ID
from shop
group by C_ID, S_ID;
现在我们有一份明确的客户名单以及他们所购买的所有公司。忠诚的客户将是那些只出现在列表中的客户。
select C_ID
from Q1
group by C_ID
having count(*) = 1;
加入第一个查询以获取公司ID:
with
Q1 as(
select C_ID, S_ID
from shop
group by C_ID, S_ID
),
Q2 as(
select C_ID
from Q1
group by C_ID
having count(*) = 1
)
select Q1.C_ID, Q1.S_ID
from Q1
join Q2
on Q2.C_ID = Q1.C_ID;
现在您有一份忠诚的客户名单,以及每个忠诚的公司。