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列的上限值分组,首先必须在派生表中执行上限。(此外,无需复制复杂表达式,更易于维护,键入错误更少等!)