Two select statement with case - sql

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.

Related

Count occurance in a row in SQLite just by SQL?

I have a DB contain 5 columns, all are integers range from 1~5 e.g.
1,1,2,3,1
5,1,2,3,4
4,2,3,2,1
....
is there a way to count number of occurrence of, say 1 in first row by just SQL ? (in this case, 3 should be return). select count() just deal with number of records return in column manner. Thanks.
Regds
LAM Chi-fung
You can combine case with count to get five columns, each with the count of the values 1 - 5:
select
case when col1 = 1 then 1 else 0 end + case when col2 = 1 then 1 else 0 end + case when col3 = 1 then 1 else 0 end + case when col4 = 1 then 1 else 0 end + case when col5 = 1 then 1 else 0 end as count_1
,case when col1 = 2 then 1 else 0 end + case when col2 = 2 then 1 else 0 end + case when col3 = 2 then 1 else 0 end + case when col4 = 2 then 1 else 0 end + case when col5 = 2 then 1 else 0 end as count_2
,case when col1 = 3 then 1 else 0 end + case when col2 = 3 then 1 else 0 end + case when col3 = 3 then 1 else 0 end + case when col4 = 3 then 1 else 0 end + case when col5 = 3 then 1 else 0 end as count_3
,case when col1 = 4 then 1 else 0 end + case when col2 = 4 then 1 else 0 end + case when col3 = 4 then 1 else 0 end + case when col4 = 4 then 1 else 0 end + case when col5 = 4 then 1 else 0 end as count_4
,case when col1 = 5 then 1 else 0 end + case when col2 = 5 then 1 else 0 end + case when col3 = 5 then 1 else 0 end + case when col4 = 5 then 1 else 0 end + case when col5 = 5 then 1 else 0 end as count_5
from table_x
You can use:
select t.*,
(col1 = 1) + (col2 = 1) + (col3 = 1) + (col4 = 1) + (col5 = 1) as num_1s
from t
SQLite treats boolean expressions like numbers in an arithmetic context, with 1 for true and 0 for false. You can also express this more verbosely as:
select t.*,
(case when col1 = 1 then 1 else 0 end +
case when col2 = 1 then 1 else 0 end +
case when col3 = 1 then 1 else 0 end +
case when col4 = 1 then 1 else 0 end +
case when col5 = 1 then 1 else 0 end +
) as num_1s
from t;
By unpivoting the data, you can get the count for all values in all columns in a single query, without the need to know the possible values in advance
sqlite> select * from t;
col1 col2 col3 col4 col5
---------- ---------- ---------- ---------- ----------
1 1 2 3 1
5 1 2 3 4
4 2 3 2 1
sqlite> select col
...> ,count(*) as cnt
...> from ( select col1 as col from t
...> union all select col2 from t
...> union all select col3 from t
...> union all select col4 from t
...> union all select col5 from t
...> )
...> group by col
...> ;
col cnt
---------- ----------
1 5
2 4
3 3
4 2
5 1
sqlite>

Count entries per row in teradata

I have a table with a row per customer and columns that are attributes about that customer. I want to know for each customer how many attributes are populated...i.e. not null values.
As an example I have this:
And I want my output to be this:
What would be the sql for this?
You can use a case expression:
select customer,
(case when col1 is not null then 1 else 0 end +
case when col2 is not null then 1 else 0 end +
case when col3 is not null then 1 else 0 end +
case when col4 is not null then 1 else 0 end +
case when col5 is not null then 1 else 0 end
) as num_entries
from t;

Return multiple rows from conditional group by without union

I am trying to build a query which supports conditional group by in SQLite DB.
Here is what I tried so far:
SELECT
case
when A>1 AND B>1 THEN 1
when X>1 AND Y>1 THEN 2
when C>1 AND D>1 THEN 3
END AS data_grp,
SUM(col1) AS col1,
SUM(col2) AS col2
FROM tbl
GROUP BY data_grp;
This Works pretty fine if only single case is true at a time. if multiple cases are true in a row then it returns the first case instead of all satisfying groups.
I have tried this by the union which works well but very slow. Is there any other way to fetch results fast with this conditional group.
Sample Data & Expected results:
DROP TABLE IF EXISTS tbl;
CREATE TABLE tbl
(
A INT,
B INT,
C INT,
D INT,
X INT,
Y INT,
col1 int,
col2 int
);
INSERT INTO tbl(A,B,C,D,X,Y,col1,col2) values (2,3,0,0,0,0,5,10);
INSERT INTO tbl(A,B,C,D,X,Y,col1,col2) values (0,0,0,0,8,10,3,2);
INSERT INTO tbl(A,B,C,D,X,Y,col1,col2) values (5,4,4,9,0,0,3,2);
SELECT
case
when A>1 AND B>1 THEN 1
when X>1 AND Y>1 THEN 2
when C>1 AND D>1 THEN 3
END AS data_grp,
SUM(col1) AS col1,
SUM(col2) AS col2
FROM tbl
GROUP BY data_grp;
Query Output :
"1" "8" "12"
"2" "3" "2"
Expected Output :
"1" "8" "12"
"2" "3" "2"
"3" "3" "2"
You can not use GROUP BY directly because of the overlapping groups.
You can use something like following, although this may also be slow.
WITH RECURSIVE
cnt(x) AS (
SELECT 1
UNION ALL
SELECT x+1 FROM cnt
LIMIT 3
)
SELECT x as data_grp, sum(col1), sum(col2)
FROM cnt,
(SELECT
case when A>1 AND B>1 THEN 1 ELSE 0 END as dg1,
case when X>1 AND Y>1 THEN 2 ELSE 0 END as dg2,
case when C>1 AND D>1 THEN 3 ELSE 0 END as dg3,
col1, col2
FROM tbl) t WHERE x=dg1 or x=dg2 or x=dg3
GROUP BY x
I am wary of summarizing data, where the result is on multiple rows and the totals don't match the original data. Of course, sometimes it is necessary, but here are two alternatives.
If you can be slightly flexible in your results, then you can concat the conditions together to get a more complex group:
SELECT ( (CASE WHEN A > 1 AND B > 1 THEN '1' ELSE '' END) ||
(CASE WHEN X > 1 AND Y > 1 THEN '2' ELSE '' END) ||
(CASE WHEN C > 1 AND D > 1 THEN '3' ELSE '' END)
) AS data_grp,
SUM(col1) AS col1, SUM(col2) AS col2
FROM tbl
GROUP BY data_grp;
I would actually write this as:
SELECT ( (CASE WHEN A > 1 AND B > 1 THEN '1' ELSE '0' END) ||
(CASE WHEN X > 1 AND Y > 1 THEN '1' ELSE '0' END) ||
(CASE WHEN C > 1 AND D > 1 THEN '1' ELSE '0' END)
) AS data_grp,
So data_grp gets a string of 0's and 1's indicating the group.
These results are not the same as your results. They are more what I would want, if I were looking at different groups -- I would want to see the overlaps between the groups.
Or, I would put the values in separate columns:
SELECT SUM(CASE WHEN A > 1 AND B > 1 THEN col1 ELSE 0 END) as sum1_1,
SUM(CASE WHEN X > 1 AND Y > 1 THEN col1 ELSE 0 END) as sum1_2,
SUM(CASE WHEN C > 1 AND D > 1 THEN col1 ELSE 0 END) as sum1_3,
SUM(CASE WHEN A > 1 AND B > 1 THEN col2 ELSE 0 END) as sum2_1,
SUM(CASE WHEN X > 1 AND Y > 1 THEN col2 ELSE 0 END) as sum2_2,
SUM(CASE WHEN C > 1 AND D > 1 THEN col2 ELSE 0 END) as sum2_3
FROM tbl;
These are the same results, but pivoted differently.

SQL Server Sum rows with string value

I have a dynamic SQL query which returns rows like below with string values & numeric values.
EMP col1 col2 col3 col4 col5
----------------------------
A1 4 4 3 3 3
A2 4 2 5 3 3
A3 sd 3 3 1 sd
A4 3 4 3 3 3
Now I need a new column which sums col1 to col5 and creates a total sum column where it should ignore the string values as in row 3. There are no NULL values
How could I achieve this? Using ISNUMERIC might be the solution, but I'm not sure how to use it in such a scenario.
You can use a CASE Expression to determine whether the value is a number. If it is a number then either cast the value to an INT or DECIMAL data type, otherwise use 0 so it doesn't effect the sum.
SELECT
CASE WHEN ISNUMERIC(col1) = 1 THEN CAST(col1 as INT) ELSE 0 END
+ CASE WHEN ISNUMERIC(col2) = 1 THEN CAST(col2 as INT) ELSE 0 END
+ CASE WHEN ISNUMERIC(col3) = 1 THEN CAST(col3 as INT) ELSE 0 END
+ CASE WHEN ISNUMERIC(col4) = 1 THEN CAST(col4 as INT) ELSE 0 END
+ CASE WHEN ISNUMERIC(col5) = 1 THEN CAST(col5 as INT) ELSE 0 END as SumValue
FROM MyTable
If you're on SQL Server 2012, TRY_CONVERT avoids pitfalls commonly encountered with ISNUMERIC:
SELECT col1, col2, col3, col4, col5,
ISNULL(TRY_CONVERT(int, col1), 0) +
ISNULL(TRY_CONVERT(int, col2), 0) +
ISNULL(TRY_CONVERT(int, col3), 0) +
ISNULL(TRY_CONVERT(int, col4), 0) +
ISNULL(TRY_CONVERT(int, col5), 0) AS total
FROM Employee
SQLFiddle
You can do this with a big case statement:
select q.*,
((case when isnumeric(col1) = 1 then cast(col1 as int) else 0 end) +
(case when isnumeric(col2) = 1 then cast(col2 as int) else 0 end) +
(case when isnumeric(col3) = 1 then cast(col3 as int) else 0 end) +
(case when isnumeric(col4) = 1 then cast(col4 as int) else 0 end) +
(case when isnumeric(col5) = 1 then cast(col5 as int) else 0 end)
) as newcol
from q;
isnumeric() should be sufficient for your purposes. You might need fancier logic if you only want positive integers or want to exclude exponential notations or the like.
You're on the right track with isnumeric:
select
emp,
(case when isnumeric(col1) = 1 then cast(col1 as int) else 0 end) +
col2...
from table1

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;