【问题标题】:Microsoft SQL is it possible to concatenate the result of two select statementsMicrosoft SQL 是否可以连接两个 select 语句的结果
【发布时间】:2016-09-18 04:06:28
【问题描述】:

我有一个包含以下信息的表格:客户、行、文本。 line 的值是 1-5,对应于一周中的几天,Mon-Fri。我们可能会看到如下数据:

|Customer | Line | Text | 
|123      | 1    | 018  |
|123      | 3    | 030  |
|234      | 2    | 129  |

周一和周三可以看到客户 123,周二可以看到客户 234。

我想为每个客户生成一行,如下所示:

123   Mon     Wed
234       Tue

我可以使用

select Customer, DaysOfWeek = 
case text
    when '' then '    '
    else 'Tue '         
end  
from routing where customer = %s and line = '2'

当 %s = '234' 时会生成“Tue”。

当我堆叠其中的五个,每个有一个由 UNION 分隔的行号 1 到 5 时,我会为客户 123 得到两个单独的行,分别是周一和周三。我无法将所有选择的结果放入语句放在一行上。我已经尝试过 CONCAT、&、+.... 我卡住了。

【问题讨论】:

  • 你使用的是什么 SQL?
  • 您使用的“Microsoft SQL”是指 Microsoft SQL Server 吗?还是您指的是 Microsoft Access SQL ?请添加sql-serverms-access 标签以澄清 - 谢谢!
  • 在我去参加我儿子的棒球比赛之前快速思考一下……您可以编写五个查询,每个查询代表一天。查询将使用 where 子句。然后,您将所有五个查询连接在一起以生成最终结果。我一回到家就会写下这些问题作为答案。
  • @Ghost 我正在尝试在应用程序上配置数据输出。我不知道他们在应用程序上使用什么 SQL。我们的服务器上有 Microsoft SQL Server,用于检查源数据库。我们被告知使用 SybaseCentral UltraLite 查看我们从下载的“容器”(.ipa 文件及其数据)中提取的数据库。在 Ultralite 中运行的查询通常会在应用程序中返回良好的结果,但并非总是如此。
  • @TychaBrahe 您的查询是在“应用程序”中工作还是您刚刚在 Ultralite 中进行了测试?我在想,如果您将别名更改为末尾并使用“As”关键字,Serg 的 SQL 可能会起作用。

标签: sql sql-server select concat


【解决方案1】:

这应该可以在您的应用中使用:

如果它在您的应用程序中不能作为 CTE(通用表表达式)工作,那么我将转换为嵌套查询,这肯定可以工作。

    WITH CUSTOMERS AS 
  (SELECT DISTINCT Customer
    FROM routing),
  DAY1 AS 
(SELECT Customer,
        Line
  FROM routing
  WHERE Line = 1
  AND isnull(Text, '') <> ''),
  DAY2 AS 
(SELECT Customer,
        Line
  FROM routing
  WHERE Line = 2
  AND isnull(Text, '') <> ''),
  DAY3 AS 
(SELECT Customer,
        Line
  FROM routing
  WHERE Line = 3
  AND isnull(Text, '') <> ''),
  DAY4 AS 
(SELECT Customer,
        Line
  FROM routing
  WHERE Line = 4
  AND isnull(Text, '') <> ''),
  DAY5 AS 
(SELECT Customer,
        Line
  FROM routing
  WHERE Line = 5
  AND isnull(Text, '') <> '')
SELECT CUSTOMERS.Customer,
  CASE WHEN DAY1.Line IS NULL THEN '' ELSE 'Mon' END AS 'Mon',
  CASE WHEN DAY2.Line IS NULL THEN '' ELSE 'Tue' END AS 'Tue',
  CASE WHEN DAY3.Line IS NULL THEN '' ELSE 'Wed' END AS 'Wed',
  CASE WHEN DAY4.Line IS NULL THEN '' ELSE 'Thu' END AS 'Thu',
  CASE WHEN DAY5.Line IS NULL THEN '' ELSE 'Fri' END AS 'Fri'
  FROM CUSTOMERS
  LEFT JOIN DAY1
  ON CUSTOMERS.Customer = DAY1.Customer
  LEFT JOIN DAY2
  ON CUSTOMERS.Customer = DAY2.Customer
  LEFT JOIN DAY3
  ON CUSTOMERS.Customer = DAY3.Customer
  LEFT JOIN DAY4
  ON CUSTOMERS.Customer = DAY4.Customer
  LEFT JOIN DAY5
  ON CUSTOMERS.Customer = DAY5.Customer

好的,我继续创建嵌套查询版本。我非常有信心这将适用于您的应用程序。

    SELECT DISTINCT C.Customer,
  CASE WHEN DAY1.Line IS NULL THEN '' ELSE 'Mon' END AS 'Mon',
  CASE WHEN DAY2.Line IS NULL THEN '' ELSE 'Tue' END AS 'Tue',
  CASE WHEN DAY3.Line IS NULL THEN '' ELSE 'Wed' END AS 'Wed',
  CASE WHEN DAY4.Line IS NULL THEN '' ELSE 'Thu' END AS 'Thu',
  CASE WHEN DAY5.Line IS NULL THEN '' ELSE 'Fri' END AS 'Fri'
    FROM routing C
  LEFT JOIN (SELECT Customer,
        Line
  FROM routing
  WHERE Line = 1
  AND isnull(Text, '') <> '') DAY1
  ON C.Customer = DAY1.Customer
  LEFT JOIN (SELECT Customer,
        Line
  FROM routing
  WHERE Line = 2
  AND isnull(Text, '') <> '') DAY2
  ON C.Customer = DAY2.Customer
  LEFT JOIN (SELECT Customer,
        Line
  FROM routing
  WHERE Line = 3
  AND isnull(Text, '') <> '') DAY3
  ON C.Customer = DAY3.Customer
  LEFT JOIN (SELECT Customer,
        Line
  FROM routing
  WHERE Line = 4
  AND isnull(Text, '') <> '') DAY4
  ON C.Customer = DAY4.Customer
  LEFT JOIN (SELECT Customer,
        Line
  FROM routing
  WHERE Line = 5
  AND isnull(Text, '') <> '') DAY5
  ON C.Customer = DAY5.Customer

【讨论】:

  • 我能想到的唯一会使其与您的应用程序不兼容的是 isnull() 函数。如果失败,您可以尝试更改它。
【解决方案2】:

如果我猜对了,

select Customer, 
  Day1 = max(case line when '1' then 'Mon ' end),  
  Day2 = max(case line when '2' then 'Tue ' end),  
  --..       
from routing 
where customer = %s 
    and Len(text) > 0 -- skip empty text rows
group by Customer

此查询将为所需的一周中的每一天返回单行和单列。

【讨论】:

  • 我喜欢这个。它在 MS SQL Server 中工作,当我将 Len() 更改为 Length() 时,它在 Ultralite 中工作。我只是无法让它在我们的应用程序中工作。实验仍在继续。
  • @Serg 我从来没有想过在这个查询中写一个像 select 子句这样的 SQL 语句。看起来它是别名,但在前面。我已经用变量完成了这个,但我从来没有想过在普通查询中尝试这个。我想我真的会喜欢它的。 :) 我没有测试过这个,所以如果我认为它是这样使用的,请纠正我。
  • @Michael 这确实是别名,但这种风格只被一些 DBMS 支持,包括 MS SQL。
  • 也许这就是查询在 OP 的应用程序中不起作用的原因。这是一个很好的功能,我使用 SQL Server,所以我将使用它。
【解决方案3】:

有两种方法: 首先是 case 和 exists 函数,例如: 选择

case when exists (SELECT 1 FROM routing r1 WHERE r1.customer=r2.customer AND r1.Line=1) then 'Mon' else '   ' end ||
case when exists (SELECT 1 FROM routing r1 WHERE r1.customer=r2.customer AND r1.Line=2) then 'Tue' else '   ' end
[... next days...]
from routing r2 group by r2.customer

第二种方法更复杂,使用 PIVOT 选择,但并非所有数据库引擎都支持。

【讨论】:

  • 这也适用于 MSSQL 和 UltraLite,但不适用于我们的应用程序。在你问之前,我不知道开发人员在应用程序中使用什么 SQL。我只是做配置。感谢您的帮助。
  • 试试我的 SQL 查询,我相信它会为你工作,即使它不是最有效的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-25
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
  • 2019-08-30
相关资源
最近更新 更多