基于第一表的第二表中具有查找的SQL复杂查询

时间:2014-06-11 02:05:39

标签: mysql sql sql-server

我一直在考虑如何做这件事近两天,但仍无济于事。如果有人能给我指点或帮我做这个SQL语句,我会很感激。所以我有这些表......

Table1  
NameField

Mark
John
Chris
Tina
Charles

Table2
NameField    ItemField

Mark         Pencil
Mark         Bag
Mark         Paper
Mark         Book
John         Book
John         Ballpen
Chris        Bag
Chris        Paper
Chris        Pencil
Tina         Ballpen
Charles      Computer
Charles      Book
Charles      Pencil
Charles      Box
Charles      Shoes

如何根据这些条件制作查询数据的SQL语句?

a)从NameField Table1 ItemFieldBag以及Paper获取所有Pencil

结果:

    Chris

b)从NameField获取所有Table1,其中ItemField BagPaperPencil额外增加0或1或2随机ItemField

结果:

    Mark, Chris

c)从NameField Table1 ItemField Pencil获取所有ItemField,无论Pencil是否有其他项目,并计算额外项目(不包括项目{{ 1}})并列出额外的项目。

结果:

    Mark - 3 - Bag, Paper, Book
    Chris - 2 - Bag, Paper
    Charles - 4 - Computer, Book, Box, Shoes

我尝试在服务器端脚本语言的帮助下执行此操作,循环遍历NameField中的每个Table1,然后再为每个ItemField循环。所以如果我在Table下有1000个项目,我需要循环1000个项目。解决方案效率低得离谱。所以我很抱歉,如果我到目前为止无法提供任何代码,因为我真的没有。什么都没有出现。这是我遇到的第一个这样的问题。非常感谢你。

3 个答案:

答案 0 :(得分:2)

我只用表2给了它一个镜头。

1)

SELECT a.NameField, 
    COUNT(DISTINCT b.ItemField) AS MatchCount, 
    COUNT(DISTINCT a.ItemField) AS TotalCount, 
    GROUP_CONCAT(DISTINCT b.ItemField) AS MatchedItems,
    GROUP_CONCAT(DISTINCT a.ItemField) AS AllItems
FROM Table2 a
LEFT JOIN Table2 b
  ON b.NameField = a.NameField
  AND b.ItemField IN ('Bag', 'Paper', 'Pencil')
GROUP BY a.NameField
HAVING TotalCount = 3 AND MatchCount = 3;

2)

SELECT a.NameField, 
    COUNT(DISTINCT b.ItemField) AS MatchCount, 
    COUNT(DISTINCT a.ItemField) AS TotalCount, 
    GROUP_CONCAT(DISTINCT b.ItemField) AS MatchedItems,
    GROUP_CONCAT(DISTINCT a.ItemField) AS AllItems
FROM Table2 a
LEFT JOIN Table2 b
  ON b.NameField = a.NameField
  AND b.ItemField IN ('Bag', 'Paper', 'Pencil')
GROUP BY a.NameField
HAVING MatchCount >= 3;

3)

SELECT a.NameField, 
    COUNT(DISTINCT b.ItemField) AS OtherItemCount, 
    GROUP_CONCAT(DISTINCT b.ItemField) AS OtherItems
FROM Table2 a
LEFT JOIN Table2 b
  ON b.NameField = a.NameField
  AND b.ItemField != 'Pencil'
WHERE a.ItemField = 'Pencil'
GROUP BY a.NameField;

确实需要输入您匹配的项目数量,但希望它有所帮助!

修改:Here's a fiddle - would be fun to see this improved upon!

答案 1 :(得分:1)

查询A非常简单,所以我将从那开始:

SELECT Namefield FROM Table2 
WHERE ItemField IN ('Bag', 'Paper', 'Pencil')
GROUP BY NameField
HAVING count(*) = 3;

查询B:在子查询中使用与上面相同的查询,但检查总项数是否小于或等于5(允许0,1,2额外)

SELECT Namefield FROM Table2 
WHERE NameField IN 
(SELECT Namefield FROM Table2 WHERE ItemField IN ('Bag', 'Paper', 'Pencil') GROUP BY NameField HAVING count(*) = 3) 
GROUP BY NameField 
HAVING count(*) <= 5;

查询C:我认为pssdbt的效果最好。请注意,包含多个这样的项目的东西应该由服务器端语言而不是SQL来处理。 SQL是数据的平面表示。

答案 2 :(得分:0)

我对其他人的看法略有不同,但它确实需要一些前期工作,其形式是使检查字符串按字母顺序排列。 我的查询的好处是它支持同一项的多次计数,例如获得3个铅笔和&amp; 2袋。

(受@pssdbt的回答启发)

查询A:

SELECT NameField, GROUP_CONCAT(ItemField ORDER BY ItemField) AS MatchedItems 
FROM Table2
GROUP BY NameField
HAVING MatchedItems = "Bag,Paper,Pencil";

查询B:

SELECT NameField, GROUP_CONCAT(DISTINCT ItemField ORDER BY ItemField) AS MatchedItems ,
count(ItemField) as totalCount 
FROM Table2
GROUP BY NameField
HAVING MatchedItems LIKE "%Bag%Paper%Pencil%" AND totalCount <= 5;

查询C:

SELECT NameField, 
  GROUP_CONCAT(DISTINCT if(ItemField="Pencil",null,ItemField) ORDER BY ItemField) AS MatchedItems, 
  SUM(if(ItemField="Pencil",0,1)) as extraCount,
  SUM(if(ItemField="Pencil",1,0)) as hasPencil
FROM Table2
GROUP BY NameField
HAVING hasPencil > 0;