Вы можете сделать это в Oracle, используя UNPIVOT
:
SQL Fiddle
Настройка схемы Oracle 11g R2 :
CREATE TABLE table_name ( ID, COL1, COL2, COL3, COL4 ) As
SELECT 1, 11, 11, 11, 44 FROM DUAL UNION ALL
SELECT 2, 11, 22, 33, 44 FROM DUAL UNION ALL
SELECT 3, 11, null, 33, 33 FROM DUAL UNION ALL
SELECT 4, 11, null, null, 44 FROM DUAL;
Запрос 1 :
SELECT *
FROM table_name
WHERE id IN (
SELECT id
FROM table_name
UNPIVOT ( value FOR key IN ( COL1, COL2, COL3, COL4 ) )
GROUP BY id, value
HAVING COUNT( DISTINCT key ) > 1
)
Результаты
| ID | COL1 | COL2 | COL3 | COL4 |
|----|------|--------|------|------|
| 1 | 11 | 11 | 11 | 44 |
| 3 | 11 | (null) | 33 | 33 |
Если вы хотите сопоставить на NULL
, просто используйте UNPIVOT INCLUDE NULLS
.
И SQL Server, с почти таким же кодом (просто нужен псевдоним на UNPIVOT
):
SQL Fiddle
Запрос 1 :
SELECT *
FROM table_name
WHERE id IN (
SELECT id
FROM table_name
UNPIVOT ( value FOR name IN ( COL1, COL2, COL3, COL4 ) ) AS u
GROUP BY id, value
HAVING COUNT( DISTINCT name ) > 1
)
Результаты :
| ID | COL1 | COL2 | COL3 | COL4 |
|----|------|--------|------|------|
| 1 | 11 | 11 | 11 | 44 |
| 3 | 11 | (null) | 33 | 33 |
Обновление
Вы также можете сгенерировать запрос грубой силы, используя таблицу словаря *_TAB_COLUMN
в Oracle (вероятно, в SQL-сервере есть эквивалент):
SELECT 'SELECT * FROM TABLE_NAME WHERE ('
|| LISTAGG(
'"' || PRIOR COLUMN_NAME || '" = "' || COLUMN_NAME || '"',
' OR '
) WITHIN GROUP ( ORDER BY ROWNUM )
|| ')' AS query
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'TABLE_NAME'
AND COLUMN_NAME LIKE 'COL%'
AND LEVEL = 2
START WITH COLUMN_NAME LIKE 'COL%'
CONNECT BY PRIOR COLUMN_ID < COLUMN_ID;
Какие выходы:
SELECT * FROM TABLE_NAME WHERE ("COL1" = "COL2" OR "COL1" = "COL3" OR "COL1" = "COL4" OR "COL2" = "COL3" OR "COL2" = "COL4" OR "COL3" = "COL4")