2015-09-28 51 views
4

如果我有一个包含名字,姓氏(它们是复合唯一的)和外卖选项(例如,SQL选择跨多列具有重复数据的行

+------+-------+---------+ 
|First | Last | Food | 
+------+-------+---------+ 
|Bob | Smith | Pizza | 
|Bob | Smith | Chips | 
|Jim | Smith | Pizza | 
|Lisa | Jones | Pizza | 
|Lisa | Jones | Chinese | 
|Lisa | James | Mexican | 
|Eric | White | Chinese | 
|Eric | White | Chips | 
+------+-------+---------+ 

我希望所有的行对应于至少有两种食物偏好的人,其中之一是比萨饼。即

+------+-------+---------+ 
|First | Last | Food | 
+------+-------+---------+ 
|Bob | Smith | Pizza | 
|Bob | Smith | Chips | 
|Lisa | Jones | Pizza | 
|Lisa | Jones | Chinese | 
+------+-------+---------+ 

结果我已经...有COUNT(*)> 1尝试了加入...组,但它并不完全工作,我多么希望。

任何帮助表示感谢,谢谢。

+0

你需要的是第一次和最后一次吃饭的人数> 1 –

+0

注意你有两个答案。既然您已经标记了sql-server和mysql,则响应会有所不同。您应该标记适当的DBMS,因为这些不是同一件事。此外,你真的应该考虑正常化,因为你发布的东西没有正常化。对名字和姓氏组合的独特限制是一个糟糕的设计,因为它阻止了两个同名的人。 –

+0

不应该'埃里克'也在你的预期结果吗? – AdamMc331

回答

1

另一种方法:P在SQL Server 2012+。

SELECT FIRST,LAST,FOOD FROM(
SELECT A.FIRST,A.LAST,B.FOOD, 
COUNT(*) OVER (PARTITION BY A.FIRST,A.LAST ORDER BY A.FIRST,A.LAST DESC) AS 'POS' 
FROM TEST_FOOD A 
INNER JOIN TEST_FOOD B 
ON A.FIRST = B.FIRST 
AND A.LAST = B.LAST 
WHERE A.FOOD = 'PIZZA') TB WHERE POS = 2 

另一种更加标准的方式在SQL Server 2005+中,第一种更快,但受MSSQL版本的限制。

SELECT C.FIRST,C.LAST,C.FOOD FROM 
(
SELECT A.FIRST,A.LAST FROM TEST_FOOD A 
INNER JOIN TEST_FOOD B 
ON A.FIRST = B.FIRST 
AND A.LAST = B.LAST 
WHERE B.FOOD = 'PIZZA' 
GROUP BY A.FIRST,A.LAST 
HAVING COUNT(*) = 2 
) TB INNER JOIN 
TEST_FOOD C 
ON TB.FIRST = C.FIRST 
AND TB.LAST = C.LAST 
0
;WITH CTE AS (
SELECT FIRST, LAST, MAX(FOOD) AS FOOD, COUNT(*) AS COUNT 
FROM TABLE1 
GROUP BY FIRST, LAST 
HAVING COUNT(*) >= 2) 
SELECT * 
FROM TABLE1 
WHERE FIRST+LAST IN (SELECT FIRST+LAST FROM CTE) 

有很多方法可以做到这一点。这只是一种方法。

+0

OP也想确保首选食物之一是披萨,这个查询将拉动至少有两种偏爱食物的任何人,不管它是否包括披萨(抱歉,复制粘贴评论@ McAdam331) –

0
select first,last,GROUP_CONCAT(food separator ',') 
from people 
group by first,last 
having count(food) > 1 AND SUM(food = 'Pizza') = 1 

组concat将带回以逗号分隔的字符串中的食物。

+------+-------+---------------+ 
|First | Last | Food   | 
+------+-------+---------------+ 
|Bob | Smith | Pizza,Chips | 
|Lisa | Jones | Pizza,Chinese | 
+------+-------+---------------+ 
+1

OP也想让肯定其中一种偏爱的食物是披萨,这个查询将拉扯任何至少有两种偏爱的食物,不管它是否包括披萨。 – AdamMc331

1

您可以通过获取出现不止一次姓和名的名单开始:

SELECT first, last 
FROM myTable 
GROUP BY first, last 
HAVING COUNT(*) > 1; 

一旦你有,你可以把它加入到你的原始表,并确保你只有选择那些名称:

SELECT m.* 
FROM myTable m 
JOIN(
    SELECT first, last 
    FROM myTable 
    GROUP BY first, last 
    HAVING COUNT(*) > 1) tmp ON tmp.first = m.first AND tmp.last = m.last; 

的问题与此查询,虽然,是它不验证人的首选食物中至少有一个是比萨饼。为此,我们可以在第一个子查询的HAVING子句中添加一个附加条件来检查一行披萨。我使用条件聚合来完成:

SELECT m.* 
FROM myTable m 
JOIN(
    SELECT first, last 
    FROM myTable 
    GROUP BY first, last 
    HAVING COUNT(*) > 1 AND SUM(food = 'Pizza') = 1) tmp ON tmp.first = m.first AND tmp.last = m.last; 

这是一个SQL Fiddle示例。

0

或者是这样的(使用McAdam331的小提琴)...

SELECT DISTINCT y.* 
      FROM mytable x 
      JOIN mytable y 
       ON y.first = x.first 
      AND y.last = x.last 
      JOIN mytable z 
       ON z.first = x.first 
      AND z.last = x.last 
      AND z.food <> y.food 
      WHERE x.food = 'pizza';