SQL显示两个值不同且与第一个值匹配的顺序

SQL显示两个值不同且与第一个值匹配的顺序,sql,sql-server-2008-r2,Sql,Sql Server 2008 R2,我正在寻找一种方法,使我能够选择在同一订单号内具有多个不同名称的所有订单,它如下所示: order - name 111-Paul 112-Paula 113-John 113-John 113-Jessica 114-Eric 114-Eric 114-John 115-Zack 115-Zack 115-Zack select order, name, count(name) from dbo.orders group by order, name having count(name)

我正在寻找一种方法,使我能够选择在同一订单号内具有多个不同名称的所有订单,它如下所示:

order - name
111-Paul
112-Paula 
113-John
113-John
113-Jessica 
114-Eric
114-Eric
114-John
115-Zack
115-Zack
115-Zack
select order, name, count(name) from dbo.orders
group by order, name
having count(name) > 1
等等

这样我就可以得到所有有两个或更多不同名称的订单:

113-John
113-Jessica
114-Eric
114-John
我可以用它做进一步的查询,但我被卡住了。有谁能给我一些关于如何解决这个问题的提示吗?我用count*试过,看起来像这样:

order - name
111-Paul
112-Paula 
113-John
113-John
113-Jessica 
114-Eric
114-Eric
114-John
115-Zack
115-Zack
115-Zack
select order, name, count(name) from dbo.orders
group by order, name
having count(name) > 1

这给了我所有的订单,其中有超过1个名称,但我不知道如何让它只显示具有不同名称的订单。

我会使用windows函数来实现这一点

例如:

select distinct order 
from 
    (select 
         order, 
         row_number() over(partition by order, name order by order asc) as rn
    ) as t1 
where rn > 1
你可以用count做同样的事情

count(*) over(partition by order,name order by order asc) as cnt
这里有一种使用exists的方法:

:

它实质上是将问题分解为:

查找具有多个不同值的订单

查找属于先前计算的列表的不同顺序名称对

当您使用COUNTname>1时,它将对这些组中的所有行进行计数,包括重复的行。对于顺序113,行113 John和113 John是2行。我将从您的表中查询不同的行,然后从中选择:

SELECT [order], [name] FROM (
    SELECT DISTINCT [order], [name] FROM dbo.orders
) A
GROUP BY [order], [name]
HAVING COUNT([name]) > 1
请注意,如果[name]为空,则不会使用COUNTname对其进行计数。如果要计算空值,请使用COUNT*。

您可以使用countdistinct name获取每个订单的唯一名称数:

select [order], count(distinct name)
from orders
group by [order]
要获得您可以使用的订单,请:

要获取这些订单的详细信息,您可以将其放在where子句中,只返回该列表中具有订单的行:

select *
from orders
where [order] in (
  select [order]
  from orders
  group by [order]
  having count(distinct name) > 1
)

我会使用秩或稠密秩,如下所示

SELECT [Order]
FROM (SELECT 
        [Order],
        RANK() OVER(PARTITION BY [Order] ORDER BY Name) AS NameRank
      FROM [StackOverflow].[dbo].[OrderAndName]) ranked
WHERE ranked.NameRank > 1
GROUP BY [Order]
子查询列组根据名称的值按顺序对名称进行种子设定。具有相同值的名称将具有相同的排名,即当一个订单有一个名称多次(如115)时,所有名称的排名将为1

分区在这里很重要,否则您将获得所有订单的所有名称的排名,而这不会给出您想要的结果

然后,它只是一个拉出秩大于1的订单的例子,如果这是一个偏好,分组可以使用distinct

然后,您可以连接到此表以获得如下顺序和名称:

SELECT oan.[Order], [Name]
FROM [StackOverflow].[dbo].[OrderAndName] oan
    INNER JOIN (SELECT [Order]
                FROM (SELECT [Order],
                        RANK() OVER(PARTITION BY [Order] ORDER BY Name) AS NameRank
                      FROM [StackOverflow].[dbo].[OrderAndName]) ranked
                WHERE ranked.NameRank > 1
                GROUP BY [Order]) twoOrMore ON oan.[Order] = twoOrMore.[Order]

好的,谢谢你们解释这两者的区别,你们真是太棒了!这是完美的,我需要一些时间来消化。我不知道你能做这样的事。非常感谢你。还需要尝试其他答案。谢谢你帮了一个新手@Fantajim不用担心,很高兴这有帮助。这类问题有几种解决方法。我更喜欢使用exists,它使用一个相关的子查询,其中内部查询可以引用外部查询。在本例中,请确保顺序相同,但名称不同。学习愉快!感谢您抽出时间回答初学者的问题。结构合理,解释清楚。我从中吸取了教训。干杯谢谢你的回答和时间来解释你在那里做了什么马尔科姆。我需要一些时间来完全理解它,但我已经看到了它的潜在用途。谢谢这真的很直截了当,多亏了这一点,有时候简单是最好的,在内部它使用了一个懒惰的假脱机,你可以直接从sql fiddle中看到执行计划,所以它和其他任何程序一样高效:我曾想过类似的事情,但不知道a:这是可能的,b:它是如何被调用的。你帮了我很多。谢谢你,艾瑞克
SELECT oan.[Order], [Name]
FROM [StackOverflow].[dbo].[OrderAndName] oan
    INNER JOIN (SELECT [Order]
                FROM (SELECT [Order],
                        RANK() OVER(PARTITION BY [Order] ORDER BY Name) AS NameRank
                      FROM [StackOverflow].[dbo].[OrderAndName]) ranked
                WHERE ranked.NameRank > 1
                GROUP BY [Order]) twoOrMore ON oan.[Order] = twoOrMore.[Order]