This question already has answers here:
Conditional Count on a field
(8 answers)
Closed last year.
I'm working with SQL Server and I want to create a view (my_View) which has these columns :
[element_1]
[element_2]
[element_3]
[element_4]
All of them are referring to the same column, named [parent_1], in another table (AT)
[parent_1] can have 4 possible values [value_1], [value_2], [value_3] and [value_4].
What I want is that, using COUNT,
[element_1] is equal to the number of times that [parent_1] is equal to [value_1]
same for [element_2], [element_3] and [element_4] equals to [value_2], [value_3] and [value_4].
Is it possible to use "==" inside the COUNT to see if it checks the criteria?
Something like this:
COUNT (AT.parent_1 == "value_1") AS element_1
COUNT (AT.parent_1 == "value_2") AS element_2
COUNT (AT.parent_1 == "value_3") AS element_3
COUNT (AT.parent_1 == "value_4") AS element_4
Thanks guys
You can use the CASE instruction for that
https://learn.microsoft.com/fr-fr/sql/t-sql/language-elements/case-transact-sql?view=sql-server-ver15
SUM (CASE WHEN AT.parent_1 = 'value_4' THEN 1 ELSE 0 END) as element_4
You can do something like:
SELECT
sum(case when parent_1 = "value_1" then 1 else 0 end) as element_1,
sum(case when parent_1 = "value_2" then 1 else 0 end) as element_2,
sum(case when parent_1 = "value_3" then 1 else 0 end) as element_3,
sum(case when parent_1 = "value_4" then 1 else 0 end) as element_4
FROM table;
create my_view as
select
-- other list of columns,
SUM (CASE WHEN AT.parent_1 = 'value_1' THEN 1 ELSE 0 END) as element_1,
SUM (CASE WHEN AT.parent_1 = 'value_2' THEN 1 ELSE 0 END) as element_2,
SUM (CASE WHEN AT.parent_1 = 'value_3' THEN 1 ELSE 0 END) as element_3,
SUM (CASE WHEN AT.parent_1 = 'value_4' THEN 1 ELSE 0 END) as element_4
from tableName AT
There is no need to use == like that of a programming language, in SQL comparison operator is =
Related
I need help How can I merge the column into a single column, here is my code, is this method is correct. I want to get the count of the selected row in the table for the columns.
SELECT
CAT_MGR,
SUM ( case when CAT_MGR = 'A' THEN 1 else 0 end ) AS DESIGN,
sum (case when CAT_MGR = 'b' THEN 1 else 0 END) AS DESIGN,
sum (case when CAT_MGR = 'c' THEN 1 else 0 END) AS DESIGN
from Table_A
GROUP BY
CAT_MGR
Can you guys help me I'm a beginner at SQL.
Thank you in advance
If you want just one row in the resultset, then remove the group by clause. Then, if you want to count the three cat mgr together, you can use in:
select
sum(case when cat_mgr = 'a' then 1 else 0 end ) as design_a,
sum(case when cat_mgr = 'b' then 1 else 0 end ) as design_b,
sum(case when cat_mgr = 'c' then 1 else 0 end ) as design_c,
sum(case when cat_mgr in ('a', 'b', 'c') then 1 else 0 end ) as design
from Table_a
You just need to make addion like below in order to get one column "Design"
SELECT
CAT_MGR,
SUM (case when CAT_MGR = 'A' THEN 1 else 0 end )
+ sum (case when CAT_MGR = 'b' THEN 1 else 0 END)
+ sum (case when CAT_MGR = 'c' THEN 1 else 0 END)
AS DESIGN
from TJD_CORE_CATPB_TB
GROUP BY
CAT_MGR
New to SQL and trying to figure this one out. I’m expecting a ratio of win % but am getting a 0 or null column
With previous as (select Venue, Row,
Count(case when place = 1 then 1 else null end) as firstx
Count(case when place = 2 then 1 else null end) as secondx
Count(case when place = 3 then 1 else null end) as thirdx
Count(case when place Between 1 and 15 then 1 else null end) as allplaces
From horses
Where racetitle not like ‘%stand%’
Group by venue, row)
Select case
When firstx = 0
Then Null
Else round(firstx/allplaces, 2)
End as winratio
From previous
Where allplaces > 10;
I want to do this with secondx and thirdx but am not sure why it is returning a column as 0 or Null???
You are getting NULL because firstx = 0 and 0 because the rdbms that you use does integer division when dividing firstx/allplaces, so multiply by 1.0 before you divide:
With previous as (
select Venue, Row,
Count(case when place = 1 then 1 end) as firstx
Count(case when place = 2 then 1 end) as secondx
Count(case when place = 3 then 1 end) as thirdx
Count(case when place Between 1 and 15 then 1 end) as allplaces
From horses
Where racetitle not like ‘%stand%’
Group by venue, row
)
Select case
When firstx = 0 Then Null
Else round(1.0 * firstx/allplaces, 2)
End as winratio
From previous
Where allplaces > 10;
I also simplified the CASE expressions inside COUNT() because there is no need for else NULL since this is the default behavior.
I assume that your DBMS makes integer division when / operates on integers. And since firstx is in general less than allplaces, then integer division of them is 0
You need to cast of of the values to a decimal number. The syntax depends on specific DBMS, usually it's CAST or CONVERT function
Some databases do integer division, which is probably the issue you are facing. That said, the more canonical way to prevent a divide-by-zero is to use nullif():
select round(firstx * 1.0/ nullif(allplaces, 0), 2) as winratio
nullif() is a standard SQL function and available in almost all databases.
This question already has answers here:
How can I get multiple counts with one SQL query?
(12 answers)
Closed 4 years ago.
I am counting specific things in a SQL Server table. I am using multiple count queries, but I am wondering if it's possible to combine them into a single query with the column name and count numbers in a single table for display.
My queries are:
select count(*) as Ask_Count
from Pld_OpenSalesOrdersLines
where left(C_Item_ID, 1) = '*'
select count(*) as M_Count
from Pld_OpenSalesOrdersLines
where (left(C_Item_ID, 1) = 'M' and len(C_Item_ID) = 1)
select count(*) as MN_Count
from Pld_OpenSalesOrdersLines
where (left(C_Item_ID, 2) = 'MN' and len(C_Item_ID) = 2)
I tried a couple stupid things to combine them, but they were a failure. I honestly can't even begin to think how to combine them, maybe it's not possible?
Thanks!
You could use CASE expression to perform conditional aggregation:
select
COUNT(CASE WHEN LEFT(C_Item_ID,1)='*' THEN 1 END) AS Ask_Count,
COUNT(CASE WHEN LEFT(C_Item_ID,1)='M' AND LEN(C_Item_ID)=1 THEN 1 END) M_Count,
COUNT(CASE WHEN LEFT(C_Item_ID,2)='MN' AND LEN(C_Item_ID)=2 THEN 1 END) MN_Count
from Pld_OpenSalesOrdersLines
Use conditional aggregation:
select sum(case when LEFT(C_Item_ID,1) = '*' then 1 else 0 end) as count_1,
sum(case when LEFT(C_Item_ID,1) = 'M' AND LEN(C_Item_ID)=1 then 1 else 0 end) as count_2,
sum(case when LEFT(C_Item_ID,2) = 'MN' AND LEN(C_Item_ID)=2 then 1 else 0 end) as count_3
from Pld_OpenSalesOrdersLines;
I would write the logic like this, though:
select sum(case when C_Item_ID like '*%' then 1 else 0 end) as count_1,
sum(case when C_Item_ID = 'M' then 1 else 0 end) as count_2,
sum(case when C_Item_ID = 'MN' then 1 else 0 end) as count_3
from Pld_OpenSalesOrdersLines;
Doing a left() on a column and then checking the length is redundant. Just use =.
I have multiple lines in a select query on db2 that use CASE with AND inside of a sum function. This worked fine on mySQL but no longer works due to the 'AND'.
Am I not able to use that keyword along with a case statement? I'm trying to aggregate these things as one value a piece and can't find IBM's direct solution to this.
Original query:
select
sum(case when legtype1 = 2 then 1 else 0 end and answered = 1) as total_inbound
, sum(case when legtype1 = 2 then 1 else 0 end and answered = 0) as total_missed
, ROUND(COALESCE(100.00 * sum(case when legtype1 = 2 and answered = 1 then 1 end)/
sum(case when legtype1 = 2 then 1 end), 100),2) as percent_answered
from table1;
I've tried
sum(case when legtype1 = 2 then 1 else 0 end, case when answered = 1 then 1 else 0 end)
But that's not correct either. I need to sum based on both conditions being satisfied, is there a different way I should go about this in DB2? I would think there would be a way to alias each condition but I've yet to find anything.
I think DB/2 is stricter about its conditionals, not letting you AND an int and a conditional, and treat the result as an argument of SUM. Essentially, it's not about AND - you should see the same problem if you try summing Booleans, e.g. SUM(answered = 1)
You should be able to push AND inside the CASE expression, like this:
select
sum(case when legtype1 = 2 and answered = 1 then 1 else 0 end) as total_inbound
, sum(case when legtype1 = 2 and answered = 0 then 1 else 0 end) as total_missed
, ROUND(COALESCE(100.00 * sum(case when legtype1 = 2 and answered = 1 then 1 end)/
sum(case when legtype1 = 2 then 1 end), 100),2) as percent_answered
from table1;
Out of interest, you can sum BOOLEAN values as of Db2 11.1.2.2
drop table table1;
create table table1(legtype1 int, answered int);
insert into table1 values (2,1),(2,1),(null, null),(2,0);
select
sum(legtype1 = 2 and answered = 1) as total_inbound
, sum(legtype1 = 2 and answered = 0) as total_missed
from table1;
TOTAL_INBOUND TOTAL_MISSED
------------- ------------
2 1
Table structures:
Solution_Votes:
ID int
SolutionID string
Vote int
Solution:
ID int
Solution
VotesUp
VotesDown
Code:
SELECT
*,
(SELECT SUM(CASE WHEN voteUp = 1 THEN 1 ELSE 0 END)
FROM Solutions_Votes) AS VoteCountUp,
(SELECT SUM(CASE WHEN voteDown = 0 THEN 1 ELSE 0 END)
FROM Solutions_Votes) AS VoteCountDown
FROM
Solution
When I run this query it gives me the count on each row for voteUpCount and voteDownCount. I need the count to be based on the solution ID so that each solution has its count of up votes and down votes. If anybody can help it would be appreciated. Thanks in advance!
Just use conditional aggregation. In your case this is simple:
select sv.solutionid,
sum(case when sv.voteUp = 1 then 1 else 0 end) as VoteCountUp,
sum(case when sv.voteDown = 0 then 1 else 0 end) as VoteCountDown
from solutions_votes sv
group by sv.solutionid;
You only need the solutions table if some solutions have no votes and you want to include them.
EDIT:
You would include solutions in various way. Here is one:
select s.*, ss.VoteCountUp, ss.VoteCountDown
from solutions s left join
(select sv.solutionid,
sum(case when sv.voteUp = 1 then 1 else 0 end) as VoteCountUp,
sum(case when sv.voteDown = 0 then 1 else 0 end) as VoteCountDown
from solutions_votes sv
group by sv.solutionid
) ss
on s.solutionid = ss.solutionid;