复杂查询指南

时间:2018-08-21 01:14:43

标签: mysql

我在编写此查询时遇到麻烦。我想出了如何通过多个查询来实现这一点,但想知道是否可以在单个查询中做到这一点。

  • 我的目标是按范围对结果进行排序。
  • 左边两列与group_id = 1有关,而右边2列与group_id = 2有关
  • 如果range1为正,则range2应该为相同的数字,但为负
  • 如果有两个行具有相同的组1,则不应将其范围分组。 (请参见range2值:-40)

数据集:

table: group_data

group_id   | range  | user_value
1          | 5      | 26  
1          | -15    | 29  
1          | 15     | 30  
2          | -40    | 12  
2          | -15    | 20  
2          | -5     | 15  
2          | -40    | 10

我的预期结果

range1 | user_value1 | user_value2 | range2
-15    | 29          |             | 15
5      | 26          | 15          | -5
15     | 30          | 20          | -15
40     |             | 12          | -40
40     |             | 10          | -40

这是我到目前为止提出的。

SELECT A.range1, A.user_value1, B.user_value2, B.range2 FROM
(
SELECT
    @row_number1:=@row_number1+1 AS RowNumber1,
    g.range as range1,
    g.user_value as user_value1
FROM 
    group_data g
(SELECT @row_number1:=0)AS x 
WHERE 
    g.group_id = 1 AND
    g.range = '-15'
ORDER BY
    g.range DESC
) as A
LEFT JOIN
(
SELECT 
    @row_number2:=@row_number2+1 AS RowNumber2,
    g.user_value as user_value2,
    g.range as range2
FROM 
    group_data g
(SELECT @row_number2:=0)AS y
WHERE 
    g.group_id = 2 AND
    g.range = '15'
ORDER BY
    g.range DESC
) as B
ON A.RowNumber1=B.RowNumber2

这将返回:

range1 | user_value1 | user_value2 | range2
-15    | 29          | (null)      | (null)

将-15和15分别切换为5和-5,它会返回:

range1 | user_value1 | user_value2 | range2
5      | 26          | 15          | -5

1 个答案:

答案 0 :(得分:1)

根据您提供的数据和预期结果,我认为此查询将满足您的要求。它使用UNION来模拟FULL OUTER JOIN上的group_data(MySQL不支持),左边group_id=1,右边{{1} }。

group_id=2

输出:

(SELECT r1.range AS range1, r1.user_value AS user_value1,
       r2.user_value AS user_value2, COALESCE(r2.range, -r1.range) AS range2
FROM       
    (SELECT *
     FROM group_data
     WHERE group_id = 1) r1
LEFT JOIN
    (SELECT *
     FROM group_data
     WHERE group_id = 2) r2
ON r1.range = -r2.range)
UNION
(SELECT COALESCE(r1.range, -r2.range) AS range1, r1.user_value AS user_value1,
       r2.user_value AS user_value2, r2.range AS range2
FROM       
    (SELECT *
     FROM group_data
     WHERE group_id = 1) r1
RIGHT JOIN
    (SELECT *
     FROM group_data
     WHERE group_id = 2) r2
ON r1.range = -r2.range)
ORDER BY range1

SQLFiddle