简体   繁体   中英

Combining multiple rows into one single row

I have a table structure like this one: so_1.png

I need to get the latest values of each column != NULL. My current approach is to use a UNION statement like this one:

SELECT TOP 1 testlong1_min, testlong1_max, NULL, NULL, NULL, NULL, NULL, NULL FROM Grenzwerte WHERE testlong1_min IS NOT NULL AND testlong1_max IS NOT NULL UNION 
SELECT TOP 1 NULL, NULL, testlong2_min, testlong2_max, NULL, NULL, NULL, NULL FROM Grenzwerte WHERE testlong2_min IS NOT NULL AND testlong2_max IS NOT NULL UNION 
SELECT TOP 1 NULL, NULL, NULL, NULL, testlong3_min, testlong3_max, NULL, NULL FROM Grenzwerte WHERE testlong3_min IS NOT NULL AND testlong3_max IS NOT NULL UNION 
SELECT TOP 1 NULL, NULL, NULL, NULL, NULL, NULL, testlong4_min, testlong4_max FROM Grenzwerte WHERE testlong4_min IS NOT NULL AND testlong4_max IS NOT NULL 

This doesn't seem to work, my result is empty. I also thought about doing 1 query per field, but I guess that'll be too much of an overhead compared to the UNION-statement.

Question:

Is there a way to concenate the columns and return the latest values in one row?

EDIT

Using Parodo's suggestion I now get this result, now I need to combine the rows into one.

在此处输入图片说明

You should use is not null instead of <> NULL as below

SELECT TOP 1 testlong1_min, testlong1_max, NULL, NULL, NULL, NULL, NULL, NULL FROM Grenzwerte WHERE testlong1_min IS NOT NULL AND testlong1_max IS NOT NULL 
UNION 
SELECT TOP 1 testlong1_min, testlong1_max, NULL, NULL, NULL, NULL, NULL, NULL FROM Grenzwerte WHERE testlong1_min IS NOT NULL AND testlong1_max IS NOT NULL 
UNION 
SELECT TOP 1 NULL, NULL, testlong2_min, testlong2_max, NULL, NULL, NULL, NULL FROM Grenzwerte WHERE testlong2_min IS NOT NULL AND testlong2_max IS NOT NULL 
UNION 
SELECT TOP 1 NULL, NULL, NULL, NULL, testlong3_min, testlong3_max, NULL, NULL FROM Grenzwerte WHERE testlong3_min IS NOT NULL AND testlong3_max IS NOT NULL 
UNION 
SELECT TOP 1 NULL, NULL, NULL, NULL, NULL, NULL, testlong4_min, testlong4_max FROM Grenzwerte WHERE testlong4_min IS NOT NULL AND testlong4_max IS NOT NULL 

Be careful with UNION because it eliminates duplicates. If you want to see duplicates use UNION ALL instead.

In the bellow statement, each CTE will have all the respective non null couples only and will also get a row number where the latest id will have number 1. So then i only get the latest id based on rownumber for each CTE, so each will have only one row. That way CROSS JOINING will result in a single row having the needed results.

;WITH testLong1CTE AS
(
    SELECT testlong1_min, testlong1_max, ROW_NUMBER()OVER(ORDER BY ID DESC) AS rn
    FROM   Table
    WHERE  testlong1_min IS NOT NULL AND testlong1_max IS NOT NULL
),testLong2CTE AS
(
    SELECT testlong2_min, testlong2_max, ROW_NUMBER()OVER(ORDER BY ID DESC) AS rn
    FROM   Table
    WHERE  testlong2_min IS NOT NULL AND testlong2_max IS NOT NULL
),testLong3CTE AS
(
    SELECT testlong3_min, testlong3_max, ROW_NUMBER()OVER(ORDER BY ID DESC) AS rn
    FROM   Table
    WHERE  testlong3_min IS NOT NULL AND testlong3_max IS NOT NULL
),testLong4CTE AS
(
    SELECT testlong4_min, testlong4_max, ROW_NUMBER()OVER(ORDER BY ID DESC) AS rn
    FROM   Table
    WHERE  testlong4_min IS NOT NULL AND testlong4_max IS NOT NULL
)
SELECT testlong1_min, 
       testlong1_max,
       testlong2_min, 
       testlong2_max,
       testlong3_min, 
       testlong3_max,
       testlong4_min, 
       testlong4_max
FROM (SELECT testlong1_min, testlong1_max FROM testLong1CTE WHERE rn = 1) AS T1
CROSS JOIN (SELECT testlong2_min, testlong2_max FROM testLong2CTE WHERE rn = 1) AS T2
CROSS JOIN (SELECT testlong3_min, testlong3_max FROM testLong3CTE WHERE rn = 1) AS T3
CROSS JOIN (SELECT testlong4_min, testlong4_max FROM testLong4CTE WHERE rn = 1) AS T4

When you combine two queries using UNION operator, the resulting resultset is the unique rows from the concatenation of both queries and that's not what you intend. If you want a single row with the latest non-null values for each column you should first get the latest non-null values and join every column into the result.

; WITH
tab1 AS (
   SELECT TOP 1 testlong1_min, testlong1_max
   FROM Grenzwerte
   WHERE testlong1_min IS NOT NULL
   ORDER BY [mySequenceColumn]
),
tab2 AS (
   SELECT TOP 1 testlong2_min, testlong2_max
   FROM Grenzwerte
   WHERE testlong2_min IS NOT NULL
   ORDER BY [mySequenceColumn]
),
tab3 AS (
   SELECT TOP 1 testlong3_min, testlong3_max
   FROM Grenzwerte
   WHERE testlong3_min IS NOT NULL
   ORDER BY [mySequenceColumn]
),
tab4 AS (
   SELECT TOP 1 testlong4_min, testlong4_max
   FROM Grenzwerte
   WHERE testlong4_min IS NOT NULL
   ORDER BY [mySequenceColumn]
),
SELECT *
FROM tab1 CROSS JOIN tab2 CROSS JOIN tab3 CROSS JOIN tab4;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM