SQL 显示 2 个值不同且与第一个值匹配的订单
SQL show orders where 2 values are distinct and match the first
我正在寻找一种方法让我 select 所有在同一订单号内有多个不同名称的订单,它看起来像这样:
order - name
111-Paul
112-Paula
113-John
113-John
113-Jessica
114-Eric
114-Eric
114-John
115-Zack
115-Zack
115-Zack
等等
这样我就能得到所有包含 2 个或更多不同名称的订单:
113-John
113-Jessica
114-Eric
114-John
我可以用它做进一步的查询,但我被卡住了。谁能给我一些关于如何解决这个问题的提示?我已经用 count(*) 试过了,它看起来像这样:
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(*) over(partition by order,name order by order asc) as cnt
这是使用 exists
的一种方法:
select distinct [order], name
from orders o
where exists (
select 1
from orders o2
where o.[order] = o2.[order] and o.name != o2.name)
Here's a straight forward implementation in Sql Server:
select distinct *
from table1
where [order] in (
select [order]
from (select distinct * from table1) iq
group by [order]
having count(*) > 1)
它基本上将问题分解为:
查找具有多个不同值的订单。
查找属于先前计算的列表的不同顺序 - 名称对。
当您使用 HAVING COUNT(name) > 1
时,它会计算这些组中的所有行,包括重复行(第 113-John 行和 113-John 是订单 113 的 2 行)。我会从您的 table 中查询不同的行,然后从中查询 select:
SELECT [order], [name] FROM (
SELECT DISTINCT [order], [name] FROM dbo.orders
) A
GROUP BY [order], [name]
HAVING COUNT([name]) > 1
请注意,如果 [name] 为空,则不会与 COUNT(name)
一起计算。如果要计算空值,请改用 COUNT(*)
。
您可以使用 count(distinct name)
获取每个订单的唯一名称的数量:
select [order], count(distinct name)
from orders
group by [order]
要获得那些您可以使用的订单:having
:
select [order]
from orders
group by [order]
having count(distinct name) > 1
要获取这些订单的详细信息,您可以将其放在 where 子句中,仅 return 列表中具有 order
的行:
select *
from orders
where [order] in (
select [order]
from orders
group by [order]
having count(distinct name) > 1
)
我会为此使用 RANK(或 DENSE_RANK),如下所示。
SELECT [Order]
FROM (SELECT
[Order],
RANK() OVER(PARTITION BY [Order] ORDER BY Name) AS NameRank
FROM [Whosebug].[dbo].[OrderAndName]) ranked
WHERE ranked.NameRank > 1
GROUP BY [Order]
子查询根据名称的值对名称进行排序(提供种子)。具有相同值的名称将具有相同的排名,即当一个订单多次使用同一个名称(如 115)时,所有名称的排名将为 1.
此处的分区很重要,否则您将获得所有订单的所有名称的排名,这不会给您想要的结果。
这只是拉出 RANK 大于 1 的订单并分组的情况(如果愿意,可以使用 distinct)。
然后您可以加入此 table 以获取以下命令和名称;
SELECT oan.[Order], [Name]
FROM [Whosebug].[dbo].[OrderAndName] oan
INNER JOIN (SELECT [Order]
FROM (SELECT [Order],
RANK() OVER(PARTITION BY [Order] ORDER BY Name) AS NameRank
FROM [Whosebug].[dbo].[OrderAndName]) ranked
WHERE ranked.NameRank > 1
GROUP BY [Order]) twoOrMore ON oan.[Order] = twoOrMore.[Order]
我正在寻找一种方法让我 select 所有在同一订单号内有多个不同名称的订单,它看起来像这样:
order - name
111-Paul
112-Paula
113-John
113-John
113-Jessica
114-Eric
114-Eric
114-John
115-Zack
115-Zack
115-Zack
等等
这样我就能得到所有包含 2 个或更多不同名称的订单:
113-John
113-Jessica
114-Eric
114-John
我可以用它做进一步的查询,但我被卡住了。谁能给我一些关于如何解决这个问题的提示?我已经用 count(*) 试过了,它看起来像这样:
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(*) over(partition by order,name order by order asc) as cnt
这是使用 exists
的一种方法:
select distinct [order], name
from orders o
where exists (
select 1
from orders o2
where o.[order] = o2.[order] and o.name != o2.name)
Here's a straight forward implementation in Sql Server:
select distinct *
from table1
where [order] in (
select [order]
from (select distinct * from table1) iq
group by [order]
having count(*) > 1)
它基本上将问题分解为:
查找具有多个不同值的订单。
查找属于先前计算的列表的不同顺序 - 名称对。
当您使用 HAVING COUNT(name) > 1
时,它会计算这些组中的所有行,包括重复行(第 113-John 行和 113-John 是订单 113 的 2 行)。我会从您的 table 中查询不同的行,然后从中查询 select:
SELECT [order], [name] FROM (
SELECT DISTINCT [order], [name] FROM dbo.orders
) A
GROUP BY [order], [name]
HAVING COUNT([name]) > 1
请注意,如果 [name] 为空,则不会与 COUNT(name)
一起计算。如果要计算空值,请改用 COUNT(*)
。
您可以使用 count(distinct name)
获取每个订单的唯一名称的数量:
select [order], count(distinct name)
from orders
group by [order]
要获得那些您可以使用的订单:having
:
select [order]
from orders
group by [order]
having count(distinct name) > 1
要获取这些订单的详细信息,您可以将其放在 where 子句中,仅 return 列表中具有 order
的行:
select *
from orders
where [order] in (
select [order]
from orders
group by [order]
having count(distinct name) > 1
)
我会为此使用 RANK(或 DENSE_RANK),如下所示。
SELECT [Order]
FROM (SELECT
[Order],
RANK() OVER(PARTITION BY [Order] ORDER BY Name) AS NameRank
FROM [Whosebug].[dbo].[OrderAndName]) ranked
WHERE ranked.NameRank > 1
GROUP BY [Order]
子查询根据名称的值对名称进行排序(提供种子)。具有相同值的名称将具有相同的排名,即当一个订单多次使用同一个名称(如 115)时,所有名称的排名将为 1.
此处的分区很重要,否则您将获得所有订单的所有名称的排名,这不会给您想要的结果。
这只是拉出 RANK 大于 1 的订单并分组的情况(如果愿意,可以使用 distinct)。
然后您可以加入此 table 以获取以下命令和名称;
SELECT oan.[Order], [Name]
FROM [Whosebug].[dbo].[OrderAndName] oan
INNER JOIN (SELECT [Order]
FROM (SELECT [Order],
RANK() OVER(PARTITION BY [Order] ORDER BY Name) AS NameRank
FROM [Whosebug].[dbo].[OrderAndName]) ranked
WHERE ranked.NameRank > 1
GROUP BY [Order]) twoOrMore ON oan.[Order] = twoOrMore.[Order]