SQL-如何跨多个表显示重复项
我有一个包含以下两个表的数据库-SQL-如何跨多个表显示重复项,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有一个包含以下两个表的数据库-部门和操作 +---------+----------+----------+ | OPS_REF | OPS_NAME | DEPT_REF | +---------+----------+----------+ | 000A | OPS1 | 0001 | +---------+----------+----------+ | 000B | Ops1 | 0001 | +---------+----------+--
部门
和操作
+---------+----------+----------+
| OPS_REF | OPS_NAME | DEPT_REF |
+---------+----------+----------+
| 000A | OPS1 | 0001 |
+---------+----------+----------+
| 000B | Ops1 | 0001 |
+---------+----------+----------+
| 000C | ops1 | 0002 |
+---------+----------+----------+
| 000D | OPS2 | 0003 |
+---------+----------+----------+
| 000E | ops2 | 0001 |
+---------+----------+----------+
| 000F | ops2 | 0004 |
+---------+----------+----------+
| 000G | OPS3 | 0004 |
+---------+----------+----------+
| 000H | OPS3 | 0005 |
+---------+----------+----------+
部门的关键值为:
DEPT_REF
DEPT_NAME
DEPT_FUNCTION
OPS_REF
OPS_NAME
DEPT_REF
操作的关键值为:
DEPT_REF
DEPT_NAME
DEPT_FUNCTION
OPS_REF
OPS_NAME
DEPT_REF
我需要解决的是一个查询,它将为我提供一个操作、操作名称
、部门、部门名称
和部门、部门职能
的列表,其中它们是重复的,但应该忽略大小写。理想情况下,它也应该有一个计数
例如:
部门
+----------+-----------+---------------+
| DEPT_REF | DEPT_NAME | DEPT_FUNCTION |
+----------+-----------+---------------+
| 0001 | Home | Live here |
+----------+-----------+---------------+
| 0002 | HOME | LIVE HERE |
+----------+-----------+---------------+
| 0003 | HOME | Live here |
+----------+-----------+---------------+
| 0004 | work | Work Here |
+----------+-----------+---------------+
| 0005 | Work | Work Here |
+----------+-----------+---------------+
| 0006 | OTHER | Other Stuff |
+----------+-----------+---------------+
操作
+---------+----------+----------+
| OPS_REF | OPS_NAME | DEPT_REF |
+---------+----------+----------+
| 000A | OPS1 | 0001 |
+---------+----------+----------+
| 000B | Ops1 | 0001 |
+---------+----------+----------+
| 000C | ops1 | 0002 |
+---------+----------+----------+
| 000D | OPS2 | 0003 |
+---------+----------+----------+
| 000E | ops2 | 0001 |
+---------+----------+----------+
| 000F | ops2 | 0004 |
+---------+----------+----------+
| 000G | OPS3 | 0004 |
+---------+----------+----------+
| 000H | OPS3 | 0005 |
+---------+----------+----------+
我要寻找的输出是一个操作名称、部门名称和部门功能的列表,以大写字母显示,并带有计数。因此,从示例数据中,我希望看到:
+----------+-----------+---------------+-------+
| OPS_NAME | DEPT_NAME | DEPT_FUNCTION | COUNT |
+----------+-----------+---------------+-------+
| OPS1 | HOME | LIVE HERE | 3 |
+----------+-----------+---------------+-------+
| OPS2 | HOME | LIVE HERE | 2 |
+----------+-----------+---------------+-------+
在单个表中查找重复项没有问题,但我不知道从何处开始跨多个表执行此操作,必须忽略大小写。如果需要区分OPS\u NAME
的大小写,可以使用
将它们转换为二进制数据类型:
SELECT UPPER(o.OPS_NAME) as OPS_NAME,
UPPER(d.DEPT_NAME) as DEPT_NAME,
UPPER(d.DEPT_FUNCTION) as DEPT_FUNCTION,
COUNT(DISTINCT CAST(o.OPS_NAME As BINARY)) AS [COUNT]
FROM Departments d
INNER JOIN Operations o
ON o.DEPT_REF = d.DEPT_REF
GROUP BY o.OPS_NAME,
d.DEPT_NAME,
d.DEPT_FUNCTION
HAVING COUNT(DISTINCT CAST(o.OPS_NAME As BINARY)) > 1
输出:
OPS_NAME DEPT_NAME DEPT_FUNCTION COUNT
OPS1 HOME LIVE HERE 3
OPS2 HOME LIVE HERE 2
编辑
您还可以使用COUNT(不同的o.OPS\u NAME COLLATE Latin1\u General\u CS\u AS)
正如评论中所建议的那样。在您的情况下,也可以使用计数(不同的二进制校验和(o.OPS\U名称))
,但在某些情况下,它可以给出重复的值。情况不应引起关注。为了便于演示,我已将数据转换为大写
试验数据
IF OBJECT_ID('tempdb..#Departments') IS NOT NULL DROP TABLE #Departments
GO
CREATE TABLE #Departments (DEPT_REF varchar(4), DEPT_NAME varchar(5), DEPT_FUNCTION varchar(11))
INSERT INTO #Departments (DEPT_REF, DEPT_NAME, DEPT_FUNCTION)
VALUES
('0001','Home','Live here')
,('0002','HOME','LIVE HERE')
,('0003','HOME','Live here')
,('0004','work','Work Here')
,('0005','Work','Work Here')
,('0006','OTHER','Other Stuff')
IF OBJECT_ID('tempdb..#Operations') IS NOT NULL DROP TABLE #Operations
GO
CREATE TABLE #Operations (OPS_REF varchar(4), OPS_NAME varchar(4), DEPT_REF varchar(4))
INSERT INTO #Operations (OPS_REF, OPS_NAME, DEPT_REF)
VALUES
('000A','OPS1','0001')
,('000B','Ops1','0001')
,('000C','ops1','0002')
,('000D','OPS2','0003')
,('000E','ops2','0001')
,('000F','ops2','0004')
,('000G','OPS3','0004')
,('000H','OPS3','0005')
实际查询
SELECT
UPPER(o.OPS_NAME) OPS_NAME
,UPPER(d.DEPT_NAME) DEPT_NAME
,UPPER(d.DEPT_FUNCTION) DEPT_FUNCTION
,COUNT(d.DEPT_NAME) COUNT
FROM #Operations o
LEFT JOIN #Departments d
ON o.DEPT_REF = d.DEPT_REF
GROUP BY o.OPS_NAME, d.DEPT_NAME, d.DEPT_FUNCTION
HAVING COUNT(d.DEPT_NAME) > 1
结果
OPS_NAME DEPT_NAME DEPT_FUNCTION COUNT
OPS1 HOME LIVE HERE 3
OPS2 HOME LIVE HERE 2
OPS3 WORK WORK HERE 2
符合ANSI SQL的答案(在派生表中执行UPPER()
):
但我更愿意建议另一种方法,定义列以使用不区分大小写的排序规则!然后分组/比较等将自动工作!(也就是说,不需要做UPPER()
)我认为你把事情复杂化了,这个案子不重要。在您的系统上运行此代码,您应该会看到SQL将字符串视为相同的东西。选择CASE WHEN'lower'='lower'然后选择'Same'或者'dispatient'end您想按列的原始值还是它们的上限值进行分组?@jarlh谢谢您的评论,我意识到OP需要什么<代码>校验和
可能导致重复,但在当前情况下,二进制校验和
不能<代码>强制转换(o.OPS\U名称为二进制)是一个很好的方法,我只选择这一个。@Y.B.将此信息添加到我的答案中,再次感谢!检查一下:SELECT'LE',BINARY\u CHECKSUM('LE')UNION ALL SELECT'Ou',BINARY\u CHECKSUM('Ou')UNION ALL SELECT'MU',BINARY\u CHECKSUM('MU')
可能是一个有点未知的问题,但这样做的好处是什么?这与其他建议的解决方案类似?是什么使它符合ANSI标准?@Zammald,根据ANSI SQL,您只能按列分组,不能按表达式分组。因此,如果要按ed列的上限值分组,首先必须在派生表中执行上限。(此外,无需复制复杂表达式,更易于维护,键入错误更少等!)