SQL-仅选择某些行(如果存在)

时间:2019-03-28 12:01:29

标签: sql

我有一个包含家庭住址和邮寄地址的表。看起来像这样:

es5

我需要编写一条SQL语句,该语句仅返回邮寄地址(MLG记录)(如果存在),否则将返回家庭地址(HOM记录)。

此表的预期结果将是:

ID   Name   StNum   StName     City    State   Zip    Type
--   ----   -----   ------     ----    -----   ---    ----
1    Joe    1234    Main St    Waco    TX      76767  HOM
1    Joe    2345    High St    Waco    TX      76763  MLG
2    Amy    3456    Broad St   Athens  GA      34622  HOM
3    Mel    987     Front St   Cary    NC      65331  HOM
3    Mel    1111    Main Ave   Hilo    HI      99779  MLG

您能提供的任何帮助将不胜感激!谢谢!

5 个答案:

答案 0 :(得分:1)

使用相关子查询

select * from
(
select *,case when Type='MLG' then 1 else 0 end as typeval
from tablename
)A where typeval in (select max(case when Type='MLG' then 1 else 0 end) from tablename b 
where a.name=b.name)

或者,如果您的数据库支持row_number(),那么您可以在下面尝试-

select * from
(
select *, row_number() over(partition by name order by case when Type='MLG' then 1 else 0 end desc)
from tablename
)A where rn=1

答案 1 :(得分:0)

如果您使用的是SQL Server,我可以使用ROW_NUMBER函数来解决。

SELECT ID, Name, StNum, StName, City, State, Zip, Type
FROM (
    SELECT *
          ,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Type DESC) AS Rn
      FROM yourtable
      ) 
  WHERE Rn = 1

答案 2 :(得分:0)

这可以使用WHERE子句来完成,该子句排除具有MLG的用户的ID

模式(MySQL v5.7)

CREATE TABLE test (
  `ID` INTEGER,
  `Name` VARCHAR(3),
  `StNum` INTEGER,
  `StName` VARCHAR(8),
  `City` VARCHAR(6),
  `State` VARCHAR(2),
  `Zip` INTEGER,
  `Type` VARCHAR(3)
);

INSERT INTO test
  (`ID`, `Name`, `StNum`, `StName`, `City`, `State`, `Zip`, `Type`)
VALUES
  ('1', 'Joe', '1234', 'Main St', 'Waco', 'TX', '76767', 'HOM'),
  ('1', 'Joe', '2345', 'High St', 'Waco', 'TX', '76763', 'MLG'),
  ('2', 'Amy', '3456', 'Broad St', 'Athens', 'GA', '34622', 'HOM'),
  ('3', 'Mel', '987', 'Front St', 'Cary', 'NC', '65331', 'HOM'),
  ('3', 'Mel', '1111', 'Main Ave', 'Hilo', 'HI', '99779', 'MLG');

查询#1

SELECT id,
       name,
       StNum,
       StName,
       City,
       State,
       Zip,
       Type
FROM test t1
WHERE t1.`Type` = 'MLG'
   OR t1.id NOT IN
   (
        SELECT id
        FROM test t2
        WHERE t2.`Type` = 'MLG'
   );

输出:

| id  | name | StNum | StName   | City   | State | Zip   | Type |
| --- | ---- | ----- | -------- | ------ | ----- | ----- | ---- |
| 1   | Joe  | 2345  | High St  | Waco   | TX    | 76763 | MLG  |
| 2   | Amy  | 3456  | Broad St | Athens | GA    | 34622 | HOM  |
| 3   | Mel  | 1111  | Main Ave | Hilo   | HI    | 99779 | MLG  |

View on DB Fiddle


或者,我的第一个哑巴版本:

可以使用UNION

模式(MySQL v5.7)

CREATE TABLE test (
  `ID` INTEGER,
  `Name` VARCHAR(3),
  `StNum` INTEGER,
  `StName` VARCHAR(8),
  `City` VARCHAR(6),
  `State` VARCHAR(2),
  `Zip` INTEGER,
  `Type` VARCHAR(3)
);

INSERT INTO test
  (`ID`, `Name`, `StNum`, `StName`, `City`, `State`, `Zip`, `Type`)
VALUES
  ('1', 'Joe', '1234', 'Main St', 'Waco', 'TX', '76767', 'HOM'),
  ('1', 'Joe', '2345', 'High St', 'Waco', 'TX', '76763', 'MLG'),
  ('2', 'Amy', '3456', 'Broad St', 'Athens', 'GA', '34622', 'HOM'),
  ('3', 'Mel', '987', 'Front St', 'Cary', 'NC', '65331', 'HOM'),
  ('3', 'Mel', '1111', 'Main Ave', 'Hilo', 'HI', '99779', 'MLG');

查询#1

SELECT id,
       name,
       StNum,
       StName,
       City,
       State,
       Zip,
       Type
FROM test t1
WHERE t1.`Type` = 'MLG'
UNION ALL
SELECT id,
       name,
       StNum,
       StName,
       City,
       State,
       Zip,
       Type
FROM test t2
WHERE t2.id NOT IN (SELECT id FROM test t3 WHERE t3.`Type` = 'MLG')
ORDER BY id;

输出

| id  | name | StNum | StName   | City   | State | Zip   | Type |
| --- | ---- | ----- | -------- | ------ | ----- | ----- | ---- |
| 1   | Joe  | 2345  | High St  | Waco   | TX    | 76763 | MLG  |
| 2   | Amy  | 3456  | Broad St | Athens | GA    | 34622 | HOM  |
| 3   | Mel  | 1111  | Main Ave | Hilo   | HI    | 99779 | MLG  |

View on DB Fiddle

答案 3 :(得分:0)

如果您使用的是SQL Server,则使用WITH TIES的另一种方式如下。

select top (1) with ties * 
from YourTableName
order by row_number() over(partition by id order by type desc)

答案 4 :(得分:0)

这是一个优先级查询。具有两个值的通常最简单的方法是将union all(或not exists)与not in一起使用。

那不能很好地概括。对于更多的值,将row_number()case一起使用很方便:

select t.*
from (select t.*,
             row_number() over (partition by id
                                order by (case when type = 'MLG' then 1 else 2 end)
                               ) as seqnum
      from t
     ) t
where seqnum = 1;

在您的特定情况下,您可以使用order by type desc,因为这两种类型恰好以相反的字母顺序排列。但是,我建议使用case,因为其意图更为明确。