【问题标题】:T-SQL query to find the required output查找所需输出的 ​​T-SQL 查询
【发布时间】:2022-01-23 02:02:59
【问题描述】:

我是 SQL 查询的新手,我有一些数据,我正在尝试查找如下所示的结果。

在我的示例数据中,由于多个位置,我的客户 ID 重复多次,我要做的是创建一个查询,以图像输出格式显示输出,

  1. 如果客户只存在一次我采取该行
  2. 如果客户存在不止一次,我检查国家;如果Country = 'US',我会选择那一行并丢弃其他人
  3. 如果客户存在不止一次且国家/地区不是美国,那么我选择第一行

请注意:我有 35 列,我不想更改 ROWS 顺序,因为我必须选择第一行,以防客户存在多次且国家/地区不是“美国”。

我尝试过的:我正在尝试使用 rank 函数执行此操作,但没有成功。不确定我的方法是否正确,请任何人分享该问题的 T-SQL 查询。

问候, 拉胡尔

样本数据:

需要输出:

【问题讨论】:

  • 提问时,您需要提供minimal reproducible example: (1) DDL 和样本数据填充,即 CREATE 表和 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上述#1 中的样本数据。 (4) 您的 SQL Server 版本 (SELECT @@version;)。全部在问题内,没有图片。
  • @YitzhakKhabinsky。谢谢,我会照顾你的观点,虽然问题是我是新手,而且图像是自动拍摄的,我只是从 Excel 中复制了数据。非常感谢您分享帖子详细信息。
  • @marc_s 我正在研究 MSSQL 2016,这只是一个标签,但我觉得无论版本如何,查询逻辑都是相同的。正确吗?
  • 如何定义非美国行的顺序?
  • 这能回答你的问题吗? Get top 1 row of each group 就用OVER (PARTITION BY cust_id ORDER BY CASE WHEN country = 'US' THEN 1 ELSE 2 END, country)

标签: sql sql-server-2016


【解决方案1】:

我创建了一个(短)dbfiddle

简短说明(仅在此处重复代码):

第一步:

-- select everyting, and 'US' as first row
SELECT 
   cust_id, 
   country,
   sales,
   CASE WHEN country='US' THEN 0 ELSE 1 END X,
   ROW_NUMBER() OVER (PARTITION BY cust_id 
                      ORDER BY (CASE WHEN country='US' THEN 0 ELSE 1 END)) R
FROM table1
ORDER BY cust_id, CASE WHEN country='US' THEN 0 ELSE 1 END;

第二步:

-- filter only rows which are first row...
SELECT * 
FROM (
   SELECT 
      cust_id, 
      country,
      sales,
      CASE WHEN country='US' THEN 0 ELSE 1 END X,
      ROW_NUMBER() OVER (PARTITION BY cust_id 
                         ORDER BY (CASE WHEN country='US' THEN 0 ELSE 1 END)) R
   FROM table1
   -- ORDER BY cust_id, CASE WHEN country='US' THEN 0 ELSE 1 END
   ) x
WHERE x.R=1

【讨论】:

    【解决方案2】:

    我不能保证性能,但它应该适用于 SQL Server 2005。假设您的表名为 CustomerData 试试这个:

    select cust_id, country, Name, Sales, [Group]
    from CustomerData
    where country = 'US'
    union
    select c.* from CustomerData c
    join (
        select cust_id, min(country) country
        from CustomerData
        where cust_id not in (
            select cust_id
            from CustomerData
            where country = 'US'
            )
        group by cust_id
    ) a on a.cust_id = c.cust_id and a.country = c.country
    

    它的工作原理是找到所有以美国为国家的记录,然后将其与每条不以美国为国家的记录中的第一个国家联合。如果 min() 没有得到你想要的国家,那么你需要找到一个替代的聚合函数来选择你想要的国家。

    【讨论】:

    • 您好,感谢您的解决方案。我想在这里提一下,我的数据几乎有30-35个字段,联合不是一个好的解决方案。此外,您的解决方案有 Min(country) 我认为这也不适用于我的数据。非常感谢您的努力,虽然我需要其他解决方案,但我使用的是 MSSQL 2016。
    • 拒绝答案是相当随意的,因为您认为 35 列对于联合来说太多了,尤其是当问题中省略了这些细节时。
    • @shawnt00 抱歉,我没想到会使用联合解决方案。如果我错过提及我有 35 列,请道歉。让我现在编辑我的查询。
    • Rahul,你意识到 * 很容易被所需的五列列表替换吗?
    • 这可以用 EXCEL 做同样的事情吗?好吧,我需要交叉验证查询的结果.. 一种单元测试,我有 3000 行,手动验证它有点问题。 Excel 解决方案也很可观。非常感谢大家的大力帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多