【问题标题】:Sql query with three conditions三个条件的sql查询
【发布时间】:2017-11-22 07:20:59
【问题描述】:

我有一个数据库,其中的表格内容如下:

message_number  message_type   message_chat
     0                IN           Hi
     1                OB           Hello
     2                IN           Help
     3                IN           Want to find this thing
     4                OB           Sure
     5                OB           Please let me know

我已经写了 5 行,因为我想在我展示的示例表中的查询中合并所有可能的情况。

现在在我的查询输出中,我想要类似的东西:

message_in                                 message_out
  Hi                                         Hello
  Help                                        NULL
  Want to find this string                   Sure
     NULL                                  Please let me know

所以我想考虑的情况是:

  1. 假设如果 message_number=0 和 message_number=1 的 message_type 值都为 IN,则将 message_chat_in 设置为 message_chat(at message_number=0),将 message_chat out 设置为 NULL 并迭代 message_number=1

    李>
  2. 如果 message_number =0 且 message_type=IN 且 message_number =1 且 message_type=OB,则将 message_chat(at message_number=0) 显示为 message_chat_in 并将 message_chat(at message_number=1) 显示为 message_out 并且不要迭代 message_number= 1;

希望我已经澄清了条件,尽管我已经在预期的输出中包含了所有三个条件。我的 sqlquery 应该是什么样子?

编辑:我使用的是 mysql 版本 5.5.8

【问题讨论】:

  • 您使用的是什么版本的 MySQL?你已经 8 岁以上了吗?
  • 我使用的是 5.5.8 版

标签: mysql sql singlestore sql-query-store


【解决方案1】:

试试下面的查询

SELECT
  q1.message_number in_num,
  q1.message_chat in_chat,
  q2.message_number out_num,
  q2.message_chat out_chat
FROM
  (
    SELECT *,@i1:=IFNULL(@i1,0)+1 num
    FROM Chat
    ORDER BY message_number
  ) q1
LEFT JOIN
  (
    SELECT *,@i2:=IFNULL(@i2,0)+1 num
    FROM Chat
    ORDER BY message_number
  ) q2
ON q2.num=q1.num+1 AND q2.message_type<>q1.message_type
WHERE q1.message_type='IN'

UNION ALL

SELECT
  q1.message_number in_num,
  q1.message_chat in_chat,
  q2.message_number out_num,
  q2.message_chat out_chat
FROM
  (
    SELECT *,@i3:=IFNULL(@i3,0)+1 num
    FROM Chat
    ORDER BY message_number
  ) q1
RIGHT JOIN
  (
    SELECT *,@i4:=IFNULL(@i4,0)+1 num
    FROM Chat
    ORDER BY message_number
  ) q2
ON q2.num=q1.num+1 AND q2.message_type<>q1.message_type
WHERE q2.message_type='OB'
  AND q1.message_type IS NULL

ORDER BY IFNULL(in_num,out_num)

SQL 小提琴 - http://sqlfiddle.com/#!9/95a515/1

第二个变种

SET @i1 = 0;
SET @i2 = 0;
SET @i3 = 0;
SET @i4 = 0;

-- the same query

SQL 小提琴 - http://sqlfiddle.com/#!9/95a515/2

或者

SELECT 0,0,0,0 INTO @i1,@i2,@i3,@i4;

-- the same query

SQL 小提琴 - http://sqlfiddle.com/#!9/95a515/5

【讨论】:

  • @Radim Bača - 真的。我忘了最后添加ORDER BY。谢谢!
  • @Leran2002 是否适用于 mysql 5.5.8 版。因为我收到一条错误消息,指出“您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本相对应的手册,以在 '@i1:=IFNULL(@i1,0)+1 num FROM 附近使用正确的语法chatlog ORDER BY message_number ) q1"。所以只是想知道这是因为版本差异还是其他原因。
  • @Srijan Sharma - 尝试使用第二个变体。我更新了我的答案。
【解决方案2】:

为什么不在这里使用分析函数?我会像这样使用 Lead() 来做:

with inc as ( 
--Do the incorporation in this block. could be subquery too 
--but its easier to read this way.

select 
case when message_type = 'IN' 
     then  message_chat 
     end as message_in

,case when LEAD(message_type) OVER (Order by message_number) = 'OB' --get the next message by number if it is type OB
    then LEAD(message_chat) OVER (order by message_number)   
    end as message_out
from input
)

select *
from inc 
where coalesce(message_in, message_out) is not null   --filter out rows where with in & out is null

【讨论】:

  • 因为MySQL中没有解析函数
  • 好吧,没注意到他还在 5.5.8 上。
【解决方案3】:

好吧,由于MySQL小于8没有解析函数,代码可能不太好理解:

with data_rn as
(
  -- this isolate consecutive rows with the same message_type
  select d1.*, count(d2.message_number) rn
  from data d1
  left join data d2 on d1.message_number > d2.message_number and d1.message_type != d2.message_type
  group by d1.message_number
),
data_rn2 as
(
    -- this marks the rows where new rows has to be added (i.e. when rn2 != 0)
    select d1.*, count(d2.message_number) rn2
    from data_rn d1
    left join data_rn d2 on d1.rn = d2.rn and d1.message_type = d2.message_type and d1.message_number > d2.message_number
    group by d1.message_number
), 
data_added as
(
    -- this add new rows
    select message_number, message_type, message_chat
    from data_rn2
    union all 
    select message_number - 0.5, 'OB', NULL from data_rn2 where message_type = 'IN' and rn2 != 0
    union all 
    select message_number - 0.5, 'IN', NULL from data_rn2 where message_type = 'OB' and rn2 != 0
    order by message_number
), data_added_rn as
(
    -- this compute new row numbering
    select d1.*, ceil((count(d2.message_number)+1)/2) rn 
    from data_added d1
    left join data_added d2 on d1.message_number > d2.message_number
    group by d1.message_number
)
-- this will do the final formating
select max(case when message_type = 'IN' then message_chat end) message_in,
       max(case when message_type = 'OB' then message_chat end) message_out
from data_added_rn
group by rn

demo

我已尝试适当地评论每个部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多