Order by -- different sequence for different criteria - sql

I want to do something like this:
select a
from table
order by
case when a='A' then b,c,d
else d,c,b
a, b, c, d are all columns of the the table.

Your question is not that clear about the result that you really expect, bu I suspect that is:
order by
case when a = 'A' then b else d end,
c,
case when a = 'A' then d else b end
Or if you want records where a = 'A' first (with the specified order), and then the rest of the records (with the other sequence), then:
order by
case when a = 'A' then 0 else 1 end,
case when a = 'A' then b else d end,
c,
case when a = 'A' then d else b end

Related

Suggested sequence of responses in query

I have such values in the letter column:
A, B, C, D, E, **X**.
I would like the select to return to me such an order of
A, B, **X**, C, D, E.
I tried with ORDER BY, but I don't know if it's a good way, or it should be SELECT Top 2 and next...
If it's only one character:
order by case when MyColumn < 'C' then 1
when MyColumn = 'X' then 2
else 3
end,
MyColumn
In this case you should assign a numeric value to each of the possible values in order to get them in the desired way. It could be something like
order by case when column = 'A' then 1
when column = 'B' then 2
when column = 'C' then 3
when column = 'X' then 4
...
else 99999999
end
This can be done using a case expression to re-position the 'X' between 'B' and 'C' as follows.
order by case when MyColumn = 'X' then 'BB' else MyColumn end

SQL : Group by and check if all, some or none are set

Lets say I have the following table:
FKEY A B C D E F
'A' 1 0 1 0 1 0
'A' 0 1 1 1 0 0
Now i want to make a group by FKEY but I just want to know if the A-F columns has 1 in one, all or none of the grouped rows.. The resulton the above table would be:
FKEY A B C D E F
'A' S S A S S N
..where S is "some", A is "all" and N is "none".
What would be the best approach to make this query. I could so some nested queries, but isnt there a smarter way?
In my real life data, the 1's and 0's are actually DATETIME and NULL's
You can use case and aggregation:
select fkey,
(case when sum(a) = 0 then 'N'
when sum(a) = count(*) then 'A'
else 'S'
end) as a,
(case when sum(b) = 0 then 'N'
when sum(b) = count(*) then 'A'
else 'S'
end) as b,
. . .
from t
group by fkey;
The above assumes that the values are only 0 and 1. If that is the case, you can actually phrase this as:
(case when max(a) = 0 then 'N'
when min(a) = 1 then 'A'
else 'S'
end) as a,
You mentioned that your 0 and 1 are actually null or non null dates. Here's a modified version of Gordon's query that caters for that:
select fkey,
(case when count(datecol) = 0 then 'all dates are null'
when count(datecol) = count(*) then 'all dates are filled'
else 'some are null, some filled'
end) as a,
...
from t
group by fkey;
COUNT(null) is 0, COUNT('2001-01-01') is 1, COUNT(*) is the row count independent of any variable. Hence, if our count of the dates was 0, all must be null. If the count of the dates was equal to the count of the rows, then all must be filled with some value, otherwise it's a mix

SQL - Based on YES or NULL value, assign new value AND concatenate new values

I have six unique columns (let's just call them A, B, C, D, E, F) that all have either YES or NULL as the value. In a new column (let's call it NEW) I need to input the column name (A, B, C, D, E, F) if the value is YES. I also need these values to be concatenated, separated by a comma.
I've been playing around with SELECT/CASE/IF/THEN/ELSE statements, but haven't had any success.
Any guidance that can be offered is appreciated.
You can use CONCAT:
SELECT CONCAT( CASE WHEN A = 'YES' THEN 'A' END,
',' + CASE WHEN B = 'YES' THEN 'B' END,
',' + CASE WHEN C = 'YES' THEN 'C' END,
',' + CASE WHEN D = 'YES' THEN 'D' END,
',' + CASE WHEN E = 'YES' THEN 'E' END) NEW
FROM dbo.YourTable
;

Select count of unique values that might appear in different columns

I am trying to get a count on values that might appear in 3 different columns but only require the count of unique values. Microsoft SQL.
Eg. value X might appear in column A, B, or C or all 3 but need to make sure I only get a unique count of value X no matter what columns it comes under.
Thanks!
If you want to count each individual occurrence of X in any column A, B, or C, then the following should work:
SELECT
SUM(CASE WHEN A = 'X' THEN 1 ELSE 0 END) +
SUM(CASE WHEN B = 'X' THEN 1 ELSE 0 END) +
SUM(CASE WHEN C = 'X' THEN 1 ELSE 0 END)
FROM yourTable
Is this what you are looking for? This will Count only 1 occurrence per row regardless of how many columns it is found in.
SELECT
ID
,SUM(CASE WHEN ColA = 'X' OR ColB = 'X' OR ColC = 'X' THEN 1 ELSE 0 END) AS ValueCount
FROM
TABLENAME
GROUP BY
ID
I guess I should show it without the group by too because you don't specify a grouping.
SELECT
,SUM(CASE WHEN ColA = 'X' OR ColB = 'X' OR ColC = 'X' THEN 1 ELSE 0 END) AS ValueCount
FROM
TABLENAME

Identify columns with varying values for each set of columns

Given a table, t:
a b c d e
1 2 3 4 7
1 2 3 5 7
3 2 4 6 7
3 2 4 6 8
What SQL query can identify the columns that has one or more instances of varying values associated with each tuple from columns a and b, ?
In table t above, columns d and e would satisfy this criterion but not column c.
For tuples <1,2> and <3,2> that come from columns a and b, column c doesn't have varying values for each tuple.
Column d has one instance of varying values for tuple <1,2> -- values 4 and 5.
Column e also has one instance of varying values for tuple <3,2> -- values 7 and 8.
Something like this should work for you using CASE, COUNT and GROUP BY:
select
a, b,
case when count(distinct c) > 1 then 'yes' else 'no' end colc,
case when count(distinct d) > 1 then 'yes' else 'no' end cold,
case when count(distinct e) > 1 then 'yes' else 'no' end cole
from t
group by a, b
SQL Fiddle Demo
Slightly indirectly:
SELECT a, b,
COUNT(DISTINCT c) AS num_c,
COUNT(DISTINCT d) AS num_d,
COUNT(DISTINCT e) AS num_e
FROM t
GROUP BY a, b;
This yields:
1 2 1 2 1
3 2 1 1 2
If the num_c or num_d or num_e column has a value greater than 1, then there are varying values. You can vary the query to list whether the column is varying for a given value of (a, b) by using a CASE statement like this:
-- v for varying, n for non-varying
SELECT a, b,
CASE WHEN COUNT(DISTINCT C) > 1 THEN 'v' ELSE 'n' END AS num_c,
CASE WHEN COUNT(DISTINCT d) > 1 THEN 'v' ELSE 'n' END AS num_d,
CASE WHEN COUNT(DISTINCT e) > 1 THEN 'v' ELSE 'n' END AS num_e
FROM t
GROUP BY a, b;
This yields:
1 2 n v n
3 2 n n v
If you really want just to know whether any set of values in the given column varies for any values of (a, b) — and not which values of (a, b) it varies for — you can use the query above as a sub-query in the FROM clause and organize things as you want.
SELECT MAX(num_c) AS num_c,
MAX(num_d) AS num_d,
MAX(num_e) AS num_e
FROM (SELECT a, b,
CASE WHEN COUNT(DISTINCT C) > 1 THEN 'v' ELSE 'n' END AS num_c,
CASE WHEN COUNT(DISTINCT d) > 1 THEN 'v' ELSE 'n' END AS num_d,
CASE WHEN COUNT(DISTINCT e) > 1 THEN 'v' ELSE 'n' END AS num_e
FROM t
GROUP BY a, b
);
This relies on v being larger than n; it is easy enough (and convenient enough) for this binary decision, but not necessarily convenient or easy if there are, say, 4 states to map.
This yields:
n v v