简体   繁体   中英

Sort Distinct Merged Columns in SQL

I have the following query:

SELECT DISTINCT A + ' ' + B + ' ' + C AS 'ABC', D
FROM Table
ORDER BY A, B

This gives the following error message:

ORDER BY items must appear in the select list if SELECT DISTINCT is specified.

I tried changing the ORDER By to this:

ORDER BY A, B, C 'ABC', D

And pretty much every variation there is of those possible combinations but the error remains.

So how can i get the distinct ABC and D first sorted by the A value, and after that the B value? (The C and D may remain unsorted and don't have to be Distinct seeing the ABC combination is already enough to indicate a unique value)

EDIT:

Alternatively, is it possible to remove duplicates based on Columns A AND B without using DISTINCT?

Since you have multiple letter words in each column, you will need to order using a window function in a derived table or CTE as shown below:

WITH ordering AS (
    SELECT A,
           B,
           C, 
           D,
           row_number() OVER (ORDER BY A,B,C,D) AS order_num
    FROM Table
)

SELECT DISTINCT A + ' ' + B + ' ' + C AS 'ABC', D
FROM ordering
ORDER BY order_num ASC

Edited: new approach based on the comment

You should use concat for string concatenation

SELECT DISTINCT CONCAT(A , ' ' , B , ' ', C) AS ABC, D
FROM Table
ORDER BY 1

Have you tried a group by?

SELECT (A + ' ' + B + ' ' + C) AS 'ABC', D
FROM Table
ORDER BY A, B
GROUP BY (A + ' ' + B + ' ' + C), D

Use WITH clause :

with a AS (
  SELECT A, B, C, concat(A , ' ' , B, ' ', C) AS abc, D
FROM table1 order by A, B, C
)
select distinct abc FROM a ;



Do NOT use single quotes to delimit column names! Only use single quotes for string and date constants. If you had done this, your code would have just worked the first time:

SELECT DISTINCT A + ' ' + B + ' ' + C AS ABC, D
FROM Table
ORDER BY ABC;
SQL>create table t (id int, c1 varchar(3), c2 varchar(3));
SQL>insert into t values (1,'AX','B');
SQL>insert into t values (2,'AB','D');
SQL>insert into t values (3,'A','XB');
SQL>select concat(c1,c2) from t order by c1, c2;    

======
AXB
ABD
AXB

                  3 rows found

You can see above that row 2 ( ABD ) is sorted after one AXB row, and before the other AXB row, as the order by c1, c2 specifies.

When you do SELECT DISTINCT , these two AXB rows will become only one row - which represents two separate rows in the table, one which is sorted before the ABD row, and one after the ABD row.

You can't put the duplicate eliminated AXB both before and after ABD . That's why

ORDER BY items must appear in the select list if SELECT DISTINCT is specified.

Thanks to Brock's example of using "row_number() OVER" i thought of a way to do it myself using PARTISION BY.

WITH ordering AS 
(
    SELECT 
        A,
        B,
        C,
        D,
        row_number() OVER 
        (
            PARTITION BY
                A,
                B,
                C
            ORDER BY 
                A,
                B,
                C
        ) AS order_num
    FROM
        Table       
)
SELECT A + ' ' + B + ' ' + C AS 'ABC', D
FROM ordering
WHERE order_num = 1
ORDER BY A, B, C

This way, instead of using DISTINCT i use "row_number() OVER ( PARTITION BY" to give all records a number, with the duplicates getting an increased number. This allows me to filter on the order_num being 1 to remove all duplicates. This way i can simply order by the original 3 columns seeing Distinct is no longer a part of the query.

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