从表格中筛选出具有不同国家/地区代码数量的记录,至少有四个国家/地区代码列中的三个

时间:2017-11-10 07:24:16

标签: mysql sql oracle

我有一个小查询

+----+---------------+--------------+---------------+--------------+
| ID | Country CodeR | CountryCodeB | CountryCodeBR | CountryCodeF |
+----+---------------+--------------+---------------+--------------+
|  1 | US            | US           | US            | UK           |
|  2 | US            | UK           | US            | PK           |
|  3 | US            | UK           | PK            | IND          |
+----+---------------+--------------+---------------+--------------+

从上表 从上表

中筛选出具有不同国家/地区代码列数的记录,至少有四个国家/地区代码列中的三个

从上表我需要的结果应该如下

+----+---------------+--------------+---------------+--------------+
| ID | Country CodeR | CountryCodeB | CountryCodeBR | CountryCodeF |
+----+---------------+--------------+---------------+--------------+
|    |               |              |               |              |
|  2 | US            | UK           | US            | PK           |
|  3 | US            | UK           | PK            | IND          |
+----+---------------+--------------+---------------+--------------+

3 个答案:

答案 0 :(得分:3)

您当前的数据结构使您的查询变得困难,因为count distinct函数在上运行,而非列。一种方法是将您的数据转换为高格式,然后按ID汇总:

SELECT t1.*
FROM yourTable t1
INNER JOIN
(
    SELECT ID
    FROM
    (
        SELECT ID, CountryCodeR AS CountryCode FROM yourTable
        UNION ALL
        SELECT ID, CountryCodeB FROM yourTable
        UNION ALL
        SELECT ID, CountryCodeBR FROM yourTable
        UNION ALL
        SELECT ID, CountryCodeF FROM yourTable
    ) t
    GROUP BY ID
    HAVING COUNT(DISTINCT CountryCode) >= 3
) t2
    ON t1.ID = t2.ID;

以上可能是您在MySQL上可以做的最好的。如果您使用的是Oracle,那么您可以使用诸如unpivot和CTE之类的东西来制作更好看的查询。

Demo

答案 1 :(得分:0)

with tbl as(

select  1 ID,'US' CountryCodeR,'US' CountryCodeB,'US' CountryCodeBR,'UK' 
CountryCodef from dual

union all           

select  2 ID,'US' CountryCodeR,'UK' CountryCodeB,'US' CountryCodeBR,'PK' CountryCodef from dual

union all

select  3 ID,'US' CountryCodeR,'UK' CountryCodeB,'PK' CountryCodeBR,'IND' CountryCodef from dual

)

select t.id,t.CountryCodeR,t.CountryCodeb,t.CountryCodebR,t.CountryCodef from tbl t

join (

select id,CountryCodeB cc from tbl

union all

select id,CountryCodeBr  from tbl

union all

select id,CountryCodeF  from tbl

)s on s.id=t.id

group by t.id,t.CountryCodeR,t.CountryCodeb,t.CountryCodebR,t.CountryCodef

having count (distinct s.cc)=3

答案 2 :(得分:0)

以下几种方法可以在不使用旋转表和自联接的情况下执行此操作:

在Oracle中,您可以将项目放入集合中,然后使用SET()获取唯一项目,并使用CARDINALITY来获取集合的大小:

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE TABLE_NAME(
  ID,
  CountryCodeR,
  CountryCodeB,
  CountryCodeBR,
  CountryCodeF
) As
SELECT 1, 'US', 'US', 'US', 'UK' FROM DUAL UNION ALL
SELECT 2, 'US', 'UK', 'US', 'PK' FROM DUAL UNION ALL
SELECT 3, 'US', 'UK', 'PK', 'IND' FROM DUAL UNION ALL
SELECT 4, 'A', 'B', 'C', 'D' FROM DUAL UNION ALL
SELECT 5, 'A', 'B', 'C', 'A' FROM DUAL UNION ALL
SELECT 6, 'A', 'B', 'A', 'D' FROM DUAL UNION ALL
SELECT 7, 'A', 'A', 'C', 'D' FROM DUAL UNION ALL
SELECT 8, 'A', 'B', 'C', 'B' FROM DUAL UNION ALL
SELECT 9, 'A', 'B', 'B', 'D' FROM DUAL UNION ALL
SELECT 10, 'A', 'B', 'C', 'C' FROM DUAL UNION ALL
SELECT 11, 'A', 'B', 'B', 'A' FROM DUAL UNION ALL
SELECT 12, 'A', 'B', 'A', 'B' FROM DUAL UNION ALL
SELECT 13, 'A', 'A', 'C', 'C' FROM DUAL UNION ALL
SELECT 14, 'A', 'A', 'A', 'B' FROM DUAL UNION ALL
SELECT 15, 'A', 'A', 'B', 'A' FROM DUAL UNION ALL
SELECT 16, 'A', 'B', 'A', 'A' FROM DUAL UNION ALL
SELECT 17, 'A', 'B', 'B', 'B' FROM DUAL UNION ALL
SELECT 18, 'A', 'A', 'A', 'A' FROM DUAL
/

CREATE TYPE StringList IS TABLE OF VARCHAR2(5)
/

查询1

SELECT *
FROM   table_name
WHERE  CARDINALITY(
         SET(
           StringList(
             CountryCodeR,
             CountryCodeB,
             CountryCodeBR,
             CountryCodeF
           )
         )
       ) >= 3

<强> Results

| ID | COUNTRYCODER | COUNTRYCODEB | COUNTRYCODEBR | COUNTRYCODEF |
|----|--------------|--------------|---------------|--------------|
|  2 |           US |           UK |            US |           PK |
|  3 |           US |           UK |            PK |          IND |
|  4 |            A |            B |             C |            D |
|  5 |            A |            B |             C |            A |
|  6 |            A |            B |             A |            D |
|  7 |            A |            A |             C |            D |
|  8 |            A |            B |             C |            B |
|  9 |            A |            B |             B |            D |
| 10 |            A |            B |             C |            C |

查询2

您还可以使用多个CASE语句:

SELECT *
FROM   table_name
WHERE  CASE
       WHEN CountryCodeR IN ( CountryCodeB, CountryCodeBR, CountryCodeF )
       THEN 1 ELSE 0
       END
       +
       CASE
       WHEN CountryCodeB IN ( CountryCodeBR, CountryCodeF )
       THEN 1 ELSE 0
       END
       +
       CASE
       WHEN CountryCodeBR IN ( CountryCodeF )
       THEN 1 ELSE 0
       END
       <= 1

<强> Results

| ID | COUNTRYCODER | COUNTRYCODEB | COUNTRYCODEBR | COUNTRYCODEF |
|----|--------------|--------------|---------------|--------------|
|  2 |           US |           UK |            US |           PK |
|  3 |           US |           UK |            PK |          IND |
|  4 |            A |            B |             C |            D |
|  5 |            A |            B |             C |            A |
|  6 |            A |            B |             A |            D |
|  7 |            A |            A |             C |            D |
|  8 |            A |            B |             C |            B |
|  9 |            A |            B |             B |            D |
| 10 |            A |            B |             C |            C |

哪些也适用于MySQL - SQLFIDDLE