how to get field name what are the field have value? - sql

i have one table sql server like below , from that table i want to get quesno, field name[what are the field have value]
QuesNo A B C D
1 1 0 1 0
2 0 0 0 1
Output :
QuesNo Result
1 A,C
2 D
Is there any possible ways to get outpu?

This ought to do it...
SELECT QuesNo, SUBSTRING(Answers, 1, LENGTH(Answers) - 1) AS Answers
FROM (
SELECT QuesNo,
CASE
WHEN A <> 0 THEN 'A,'
ELSE ''
END +
CASE
WHEN B <> 0 THEN 'B,'
ELSE ''
END +
CASE
WHEN C <> 0 THEN 'C,'
ELSE ''
END +
CASE
WHEN D <> 0 THEN 'D,'
ELSE ''
END AS Answers
FROM yourtable
) Foo

Related

Hello! is that anyway to write similar query without using union?

is that anyway to write similar query without using union?
select sum(decode(p.sumsend,0,1,0)) recvcnt,
sum(decode(p.sumsend,0,1,0)*p.sumserv) recvsum
from some_table p
where p.polefilter = 5
union
select sum(decode(p.sumsend,0,1,0)) recvcnt,
sum(decode(p.sumsend,0,1,0)*p.sumserv) recvsum
from some_table p
where p.polefilter != 5
If you are OK with having all 4 columns on one row, then one option is conditional aggregation:
select
sum(case when polefilter = 5 and sumsend = 0 then 1 else 0 end) recvcnt1,
sum(case when polefilter = 5 and sumsend = 0 then 1 else 0 end * sumserv) recvsum1,
sum(case when polefilter <> 5 and sumsend = 0 then 1 else 0 end) recvcnt2,
sum(case when polefilter <> 5 and sumsend = 0 then 1 else 0 end * sumserv) recvsum2
from some_table p
where polefilter is not null
On the other hand, if you want two rows in the resultset, then you can use aggregation and a case expression to define the groups:
select
case when polefilter = 5 then 1 else 0 end as polefilter_is_5
sum(case when sumsend = 0 then 1 else 0 end) recvcnt,
sum(case when sumsend = 0 then 1 else 0 end * sumserv) recvsum1
from some_table p
where p.polefilter is not null
group by case when polefilter = 5 then 1 else 0 end
Note that I changed the decode() functions to case expressions; both do the same thing, but the latest is standard SQL (and is somehow more flexible).
A query like the one below should work. Please provide sample data and expected output when asking a question next time.
SELECT SUM (CASE WHEN p.sumsend = 0 THEN 1 ELSE 0 END) recvcnt,
SUM (CASE WHEN p.sumsend = 0 THEN 1 ELSE 0 END * p.sumserv) recvsum
FROM some_table p
GROUP BY CASE p.polefilter WHEN 5 THEN 1 ELSE 0 END;

Two select statement with case

I have two queries and I have a value if value is 1 then first query will execute if value is 2 then second. How can i achieve this, my query is
Query one if value is 1
SELECT count (CASE WHEN col1 = 9 THEN 1 ELSE 0 END )AS "matches" ,
CAST( CASE WHEN col1 = 9 THEN 1 ELSE 0 END AS VARCHAR(10)) + ' / 1' AS "match by"
FrOM table a
where ( SELECT CASE WHEN col1 = 9 THEN 1 ELSE 0 END AS "matches" ) >= 1
group by ( CASE WHEN col1 = 9 THEN 1 ELSE 0 END )
)
Query 2 if value 2
SELECT count (CASE WHEN col1 = 9 THEN 1 ELSE 0 END +
CASE WHEN col2 = 10 THEN 1 ELSE 0 END
)AS "matches" ,
CAST( CASE WHEN col1 = 9 THEN 1 ELSE 0 END
+ CASE WHEN col2 = 10 THEN 1 ELSE 0 END AS VARCHAR(10)) + '/ 2' AS "match by"
FrOM table a
where ( SELECT CASE WHEN col1 = 9 THEN 1 ELSE 0 END +
CASE WHEN col2 = 10 THEN 1 ELSE 0 END AS "NUM_OF_MATCHES" ) >= 1
group by ( CASE WHEN col1 = 9 THEN 1 ELSE 0 END+
CASE WHEN col2 = 10 THEN 1 ELSE 0 END )
I have try it using case but it is not working
I want if value = 1 then first query will run and if value = 2 then second
although both queries doing same work but if value is 1 then col1 logic will take only col1 and if value is 2 then it will take col1 and col2 if value is 3 then it will take col1 col2 and col3 till 6 col
You can make use of a simple if else if and execute both the queries.
IF(#value=1)
BEGIN
SELECT count (CASE WHEN col1 = 9 THEN 1 ELSE 0 END )AS "matches" ,
CAST( CASE WHEN col1 = 9 THEN 1 ELSE 0 END AS VARCHAR(10)) + ' / 1' AS "match by"
FrOM table a
where ( SELECT CASE WHEN col1 = 9 THEN 1 ELSE 0 END AS "matches" ) >= 1
group by ( CASE WHEN col1 = 9 THEN 1 ELSE 0 END )
)
END
ELSE IF(#value=2)
BEGIN
SELECT count (CASE WHEN col1 = 9 THEN 1 ELSE 0 END +
CASE WHEN col2 = 10 THEN 1 ELSE 0 END
)AS "matches" ,
CAST( CASE WHEN col1 = 9 THEN 1 ELSE 0 END
+ CASE WHEN col2 = 10 THEN 1 ELSE 0 END AS VARCHAR(10)) + '/ 2' AS "match by"
FrOM table a
where ( SELECT CASE WHEN col1 = 9 THEN 1 ELSE 0 END +
CASE WHEN col2 = 10 THEN 1 ELSE 0 END AS "NUM_OF_MATCHES" ) >= 1
group by ( CASE WHEN col1 = 9 THEN 1 ELSE 0 END+
CASE WHEN col2 = 10 THEN 1 ELSE 0 END )
END
still are you using CASE Statement, why dont you try to use IIF Statement, IIF Statement is more efficient and fast compare to CASE Statement.
e.g.
select IIF(1=1, (your desired column1),(your desired column2)) as matches
you can also use nested IIF Statement in single query like CASE Statement..
select IIF(1=1, (IIF(2=2, (your desired column1),(your desired column2))),(your desired column3)) as matches.

Case statement result to another case

I need to combine below logic and put it in a sql statement.
Logic:
CASE WHEN (ABC = 2)
THEN 0
ELSE 1
END XYZ
IF XYZ > 1
THEN
FINAL_COLUMN = 10
ELSE
FINAL_COLUMN = 20
SQL :
select (CASE WHEN(CASE ABC=2 then 0 Else 1 END AS) XYZ >123
Then 10 ELSE 100 ) END AS FINAL_COLUMN
from Table 1;
The syntax for the case statement is
Case
When Condition1 Then Value
When Condition2 Then Value2
Else Value
End
So your statement should look like
Select CASE WHEN ABC = 2 Then 0 Else 1 End AS FINAL_COLUMN from Table 1;

How to count amount of data for each row

I have this table:
ID Name 01 02 03 04 05 06 07
0000068 Name1 V VX
0000069 Name2 V VX VX V V
0000070 Name3 V V V V V V
This is an table for absence check and I want to count the amount of data from each row from column 01 to 07, so I expect the first row will give result of 2, second row 5, and third row 6. And if possible I want that result to be added as a new column. Is there a way to work this somehow?
If it's always V or VX you could replace the VX with V, concatenate
them together and take the LEN():
SELECT *, LEN(REPLACE([01]+[02]+[03]+[04]+[05]+[06]+[07],'X','')) AS New_Ct
FROM YourTable
If the blanks are actually NULL you'd have to wrap them in ISNULL():
SELECT *, LEN(REPLACE(ISNULL([01],'')+ISNULL([02],'')+ISNULL([03],'')+ISNULL([04],'')+ISNULL([05],'')+ISNULL([06],'')+ISNULL([07],''),'X','')) AS New_Ct
FROM Table1
Demo: SQL Fiddle
If the number of columns is static, you can use a simple CASE expression.
SELECT *,
CASE WHEN [01] = '' OR [01] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [02] = '' OR [02] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [03] = '' OR [03] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [04] = '' OR [04] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [05] = '' OR [05] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [06] = '' OR [06] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [07] = '' OR [07] IS NULL THEN 0 ELSE 1 END [cnt]
FROM Table1;
An SQLfiddle to test with.
SELECT 01+02+03+04+05+06+07 AS total_number FROM table_name;
Try Like this
SELECT ID,Name,
(Case When[01] IS Null or [01] = '' then 0 else 1 end) +
(Case When[02] IS Null or [02] = '' then 0 else 1 end) +
(Case When[03] IS Null or [03] = '' then 0 else 1 end) +
(Case When[04] IS Null or [04] = '' then 0 else 1 end) +
(Case When[05] IS Null or [05] = '' then 0 else 1 end) +
(Case When[06] IS Null or [06] = '' then 0 else 1 end) +
(Case When[07] IS Null or [07] = '' then 0 else 1 end) AS Total
FROM table1;
FIDDLE DEMO

Using Boolean to determine 5-way Where clause

I'm looking at 5 different columns (db made badly unfortunately). If of the five columns two have one "1" value and one "2" value I want this record to be excluded from the results. However, if it only has one of the two values I want it to be included.
I have this so far, but I'm certain it will not include the record if it has even one of the two values.
NOT ((Ew.DocRecvd1 = 10 OR Ew.DocRecvd1 = 11) OR
(Ew.DocRecvd2 = 10 OR Ew.DocRecvd2 = 11) OR
(Ew.DocRecvd3 = 10 OR Ew.DocRecvd3 = 11) OR
(Ew.DocRecvd4 = 10 OR Ew.DocRecvd4 = 11) OR
(Ew.DocRecvd5 = 10 OR Ew.DocRecvd5 = 11))
Thanks.
I would suggest that you count the number of values in each group that you want. And, I would do it in a subquery, just because that makes the code more readable and maintainable.
Here is an example:
from (select t.*,
((case when Ew.DocRecvd1 in (10, 11) then 1 else 0) +
(case when Ew.DocRecvd2 in (10, 11) then 1 else 0) +
(case when Ew.DocRecvd3 in (10, 11) then 1 else 0) +
(case when Ew.DocRecvd4 in (10, 11) then 1 else 0) +
(case when Ew.DocRecvd5 in (10, 11) then 1 else 0) +
) as Num1s,
<something similar> as Num2s
from table t
) t
where Num1s = 2 and Num2s = 1;
You state the filter conditions simply in the where clause. Given a table
create table foobar
(
id int not null primary key ,
c1 int not null ,
c2 int not null ,
c3 int not null ,
c4 int not null ,
c5 int not null ,
)
go
You can say
select *
from foobar
where not ( 2 = case c1 when 1 then 1 else 0 end
+ case c2 when 1 then 1 else 0 end
+ case c3 when 1 then 1 else 0 end
+ case c4 when 1 then 1 else 0 end
+ case c5 when 1 then 1 else 0 end
and 1 = case c1 when 2 then 1 else 0 end
+ case c2 when 2 then 1 else 0 end
+ case c3 when 2 then 1 else 0 end
+ case c4 when 2 then 1 else 0 end
+ case c5 when 2 then 1 else 0 end
)
The other approach which might run faster is to use as mask table, containing the conditions you want to exclude. Something like this one:
create table mask
(
c1 tinyint null ,
c2 tinyint null ,
c3 tinyint null ,
c4 tinyint null ,
c5 tinyint null ,
unique clustered ( c1,c2,c3,c4,c5) ,
)
In your case, there are only 30 conditions to be excluded:
c1 c2 c3 c4 c5
---- ---- ---- ---- ----
NULL NULL 1 1 2
NULL NULL 1 2 1
NULL NULL 2 1 1
NULL 1 NULL 1 2
NULL 1 NULL 2 1
NULL 1 1 NULL 2
NULL 1 1 2 NULL
NULL 1 2 NULL 1
NULL 1 2 1 NULL
NULL 2 NULL 1 1
NULL 2 1 NULL 1
NULL 2 1 1 NULL
1 NULL NULL 1 2
1 NULL NULL 2 1
1 NULL 1 NULL 2
1 NULL 1 2 NULL
1 NULL 2 NULL 1
1 NULL 2 1 NULL
1 1 NULL NULL 2
1 1 NULL 2 NULL
1 1 2 NULL NULL
1 2 NULL NULL 1
1 2 NULL 1 NULL
1 2 1 NULL NULL
2 NULL NULL 1 1
2 NULL 1 NULL 1
2 NULL 1 1 NULL
2 1 NULL NULL 1
2 1 NULL 1 NULL
2 1 1 NULL NULL
(30 row(s) affected)
The actual query is trivial then (and if you have a covering index on the columns to be tested, the test is done with index seeks and so should perform extremely well:
select *
from dbo.foobar t
where not exists ( select *
from mask m
where t.c1 = m.c1
and t.c2 = m.c2
and t.c3 = m.c3
and t.c4 = m.c4
and t.c5 = m.c6
)
The advantage of this approach is that the ruleset is table-driven, meaning future changes to the rules are just data modifications to your mask table.
You could also use a positive set of rules, but in your case, the set is bigger (>200 positive cases as opposed to the 30 negative cases).
OK, I think I've found the result I wanted.
I used the following in the WHERE clause of my query:
NOT
(2 =
(CASE WHEN Ew.DocRecvd1 = 10 THEN 1 ELSE 0 END
+
CASE WHEN Ew.DocRecvd2 = 10 THEN 1 ELSE 0 END
+
CASE WHEN Ew.DocRecvd3 = 10 THEN 1 ELSE 0 END
+
CASE WHEN Ew.DocRecvd4 = 10 THEN 1 ELSE 0 END
+
CASE WHEN Ew.DocRecvd5 = 10 THEN 1 ELSE 0 END
+
CASE WHEN Ew.DocRecvd1 = 11 THEN 1 ELSE 0 END
+
CASE WHEN Ew.DocRecvd2 = 11 THEN 1 ELSE 0 END
+
CASE WHEN Ew.DocRecvd3 = 11 THEN 1 ELSE 0 END
+
CASE WHEN Ew.DocRecvd4 = 11 THEN 1 ELSE 0 END
+
CASE WHEN Ew.DocRecvd5 = 11 THEN 1 ELSE 0 END))
It is only possible in my DB to get these two documents in one of five places within one record, so the count could not go over 2 with the two documents i'm looking for.
Kudos to Nicholas Carey and Gordon Linoff for keying me into what I could do and look for!