Reputation: 3406
I have this table BarCode
, when I do a in query like this
SELECT Barcode
FROM BarcodeTable
WHERE BarCode IN
(
'53-3-1',
'51-1-1',
'51-2-1',
'50-10-1',
'50-8-1',
'51-4-1',
'50-1-1'
)
why do I get
53-3-1
50-1-1
50-8-1
50-10-1
51-1-1
51-2-1
51-4-1
Instead of ????
53-3-1
51-1-1
51-2-1
50-10-1
50-8-1
51-4-1
50-1-1
Why does SQL changing the order of barcodes? Because of the way SQL is ordering them (by itself) is causing an error in a dynamic query that is being executed by sp_executesql
that relies on the order I send the input. Why is the SQL changing input order by itself?
51-4-1
Upvotes: 1
Views: 90
Reputation: 21
Try Below Code
SELECT Barcode ,CASE Col_Order WHEN '53-3-1' THEN 1
WHEN '51-1-1' THEN 2
WHEN '51-2-1' THEN 3
WHEN '50-10-1' THEN 4
WHEN '50-8-1' THEN 5
WHEN '51-4-1' THEN 6
WHEN '50-1-1' THEN 7
END
FROM BarcodeTable
WHERE BarCode IN
(
'53-3-1',
'51-1-1',
'51-2-1',
'50-10-1',
'50-8-1',
'51-4-1',
'50-1-1'
)
ORDER BY Col_Order
Upvotes: 0
Reputation: 391306
IN
does not imply any ordering of the final result:
This SQL:
... WHERE x IN (1, 2, 3)
Should produce the same results as this:
... WHERE x IN (3, 2, 1)
The IN
clause only filters the rows, basically, for each row you can think of it as just asking "should this row be part of the resultset?".
To get a specific ordering, you're going to have to add an ORDER BY
clause to your statement.
To get a specific order, you can use an inline table:
SELECT Barcode
FROM BarcodeTable
inner join (values
('*53-3-1*', 1),
('*51-1-1*', 2),
('*51-2-1*', 3),
('*50-10-1*', 4),
('*50-8-1*', 5),
('*51-4-1*', 6),
('*50-1-1*', 7)) as DummyTable (value, sortorder)
on BarCode = value
order by
sortorder
This will order by the sortorder field of the DummyTable.
You can not trick SQL Server into using the IN
clause itself for ordering, you have to add an ORDER BY
in some form or another.
You can also use a CASE WHEN ...
expression to produce the sort order value depending on the barcode:
SELECT Barcode
FROM BarcodeTable
WHERE BarCode IN ('*53-3-1*', '*51-1-1*', '*51-2-1*', '*50-10-1*', '*50-8-1*', '*51-4-1*', '*50-1-1*')
ORDER BY
CASE BarCode
WHEN '*53-3-1*' THEN 1
WHEN '*51-1-1*' THEN 2
WHEN '*51-2-1*' THEN 3
WHEN '*50-10-1*' THEN 4
WHEN '*50-8-1*' THEN 5
WHEN '*51-4-1*' THEN 6
WHEN '*50-1-1*' THEN 7
END
As the comment by Lieven suggests, there's an alternative on SQL Server 2005, using the WITH
clause:
WITH DummyTable (value, sortorder) AS (
SELECT '*53-3-1*' AS value, 1 AS sortorder
UNION ALL
SELECT '*51-1-1*', 2
UNION ALL
SELECT '*51-2-1*', 3
UNION ALL
SELECT '*50-10-1*', 4
UNION ALL
SELECT '*50-8-1*', 5
UNION ALL
SELECT '*51-4-1*', 6
UNION ALL
SELECT '*50-1-1*', 7
)
SELECT Barcode
FROM BarcodeTable
inner join DummyTable
on BarCode = value
order by
sortorder
(note, I'm no expert in the usage of WITH
, the above was just something I hacked together, but seems to work)
Upvotes: 3
Reputation: 180887
To make your query order as you're expecting, you need to add an ORDER BY
, or the ordering will be unreliable. Something like this should work but depending on your volume of barcodes it may in the end be easier to order it correctly in code once the result is returned;
SELECT Barcode
FROM BarcodeTable
WHERE BarCode IN ('*53-3-1*','*51-1-1*','*51-2-1*','*50-10-1*',
'*50-8-1*','*51-4-1*','*50-1-1*')
ORDER BY CASE BarCode WHEN '*53-3-1*' THEN 1
WHEN '*51-1-1*' THEN 2
WHEN '*51-2-1*' THEN 3
WHEN '*50-10-1*' THEN 4
WHEN '*50-8-1*' THEN 5
WHEN '*51-4-1*' THEN 6
WHEN '*50-1-1*' THEN 7
END
Upvotes: 1
Reputation: 22074
Unless you specify an order by statement, you should not rely on particular order in the output. You must provide an ORDER BY
to get what you expect.
Upvotes: 3