按列选择每个组中不同的项目
Posted
技术标签:
【中文标题】按列选择每个组中不同的项目【英文标题】:Select item that is different in each of group by a column 【发布时间】:2018-08-23 08:22:36 【问题描述】:我有这个示例表
+--------+-------------+
| DBName | Description |
+--------+-------------+
| A | Car |
| A | Boat |
| B | Car |
| B | Plane |
| C | Car |
| C | Boat |
| C | Plane |
+--------+-------------+
我只想获取每个 DBName 上不存在的描述,并显示没有描述的 DBName。
我想要的查询结果
+--------+-------------+
| DBName | Description |
+--------+-------------+
| A | Plane |
| B | Boat |
+--------+-------------+
请记住,它不仅仅是 DBName 上的 A、B、C。
【问题讨论】:
是否有包含所有可能描述的查找表? 您可以尝试对描述进行区分并将其假设为主数据 【参考方案1】:有趣的问题。这里有几个解决方案。围绕这些技术 here 进行了讨论,并提出了一些其他处理此类情况的路线的建议。
SQL Fiddle Example
select DBName, Description
from (
select DBName, Description
from (select distinct DBName from demo) a
cross join (select distinct Description from demo) b
) c
except
select DbName, Description from demo
此解决方案的工作原理是获取所有可能的组合(通过每列不同值的交叉连接),然后通过except
子句排除所有已经存在的组合。
SQL Fiddle Example
select [each].DBName, missing.Description
from (select distinct DBName from demo) [each]
cross join (select distinct Description from demo) [missing]
where not exists
(
select top 1 1
from demo [exists]
where [exists].DbName = [each].DBName
and [exists].Description = [missing].Description
)
此解决方案与上述相同,只是我们使用where not exists
代替except
cluase 来删除现有的组合。
【讨论】:
第二个查询(不存在的地方)返回不正确的 C 船,第一个查询对我有用 谢谢@AdinugrahaTawaqal。仅供参考:第二个查询应该有效;只有我在演示数据上犯了一个错误(填充了两次C, Car
,而不是包括C, Boat
)。现在正在调整 SQL Fiddle 链接...
没问题,我应该说谢谢。【参考方案2】:
理想情况下,您应该有一个主数据列表。如果你不这样做,你应该从数据中导出它,然后像下面这样对它们进行检查:
SQL Fiddle Example
select
masterlistDbname.Dbname,
masterlistDesc.Description
from
(
select distinct Description from yourtable
) masterlistDesc
cross join
(
select distinct Dbname from yourtable
) masterlistDbname
left join
yourtable t1
on t1.Dbname = masterlistDbname.Dbname
and t1.Description = masterlistDesc.Description
where t1.Dbname is NULL
【讨论】:
我试图解决的是我在多个数据库上拥有主数据,相同的结构不同的内容。我想让主数据描述统一或至少尝试指出数据库之间的差异。每个数据库都是它自己的公司,我在控股公司工作。【参考方案3】:使用NOT EXISTS
SELECT *
FROM yourtable t
WHERE NOT EXISTS
(
SELECT *
FROM yourtable x
WHERE x.Description = t.Description
AND x.DBName <> t.DBName
)
【讨论】:
有一个小问题,它只会返回来自yourtable
的记录;所以不会完成选择那些不存在于该表中的记录的任务,因为它们不存在。【参考方案4】:
你应该多扔一些样本数据。
试试这个,
create table #test(DBName varchar(50),Descriptions varchar(50) )
insert into #test VALUES
('A','Car')
,('A','Boat')
,('B','Car')
,('B','Plane')
,('C','Car')
,('C','Boat')
,('C','Plane')
;
WITH CTE
AS (
SELECT *
,ROW_NUMBER() OVER (
ORDER BY (
SELECT NULL
)
) rn
,ROW_NUMBER() OVER (
PARTITION BY DBName ORDER BY (
SELECT NULL
)
) rn1
FROM #test
)
SELECT t.DBName
,t1.Descriptions
FROM cte t
CROSS APPLY (
SELECT TOP 1 Descriptions
FROM cte t1
WHERE t1.rn > t.rn
AND t.Descriptions <> t1.Descriptions
AND t.dbname <> t1.dbname
ORDER BY t1.rn
) t1
WHERE t.rn1 = 1
drop table #test
【讨论】:
以上是关于按列选择每个组中不同的项目的主要内容,如果未能解决你的问题,请参考以下文章