Count how many columns are bigger than 0 - sql

I have a table that has some numeric columns. I need to count how many have values that are greater than 0, and to add it as a new column.
For example:
The current table is:
A | B | C | D | E |
2 | 4 | 0 | 8 | 0 |
0 | 0 | 0 | 0 | 1 |
The output would be:
A | B | C | D | E | "New column"
2 | 4 | 0 | 8 | 0 | 3
0 | 0 | 0 | 0 | 1 | 1

You can do this with the brute force method:
select t.*,
((case when a > 0 then 1 else 0 end) +
(case when b > 0 then 1 else 0 end) +
(case when c > 0 then 1 else 0 end) +
(case when d > 0 then 1 else 0 end) +
(case when e > 0 then 1 else 0 end)
) as NewColumn
from currenttable t;
If you actually want a new column in the table, then you should do:
alter the table to add the new column
run an update statement similar to the above select
consider a trigger to keep the value up-to-date
EDIT:
Alex's comment is worth mentioning. In the more recent versions of Oracle, you can add a virtual column which would do this calculation as part of the table definition itself. Virtual columns are definitely a better way to solve this problem than adding a new non-virtual column to the table.

Related

SQL- count the non NULL values and count the rows that has string "1"

I'm trying to count non null row in a column but it's counting all the rows and and count the rows in a column that has string "1".
I was able to count the rows in a column that has string "1" for the 1st column but on the 2nd one, it's count the "0" too.
I've seen some articles here but it didn't resolved the issue.
SELECT NAME as Agent_Name, COUNT(case when Thumbs_Up= 1 then 1 else null end) as Thumbs_Up,
COUNT(case when No_Solution_Found =1 then 1 else null end) as No_Solution,
COUNT(case when Save is null then 0 else 1 end) as Total_Saves,
FROM table
GROUP BY NAME
Table:
Name | Thumbs_up | No_Solution_Found | Save
Jonathan | 1 | 0 | Saved
Mike | 0 | 1 | Null
Peter | 1 | 0 | Null
Mike | 1 | 0 | Saved
Peter | 0 | 1 | Saved
Mike | 1 | 0 | Saved
Peter | 0 | 1 | Saved
Expected results:
Name | Thumbs_up | No_Solution | Total_Save
Jonathan | 1 | 0 | 1
Mike | 2 | 1 | 2
Peter | 1 | 2 | 2
Try with SUM instead of COUNT
SELECT NAME as Agent_Name,
SUM(case when Thumbs_Up = 1 then 1 else 0 end) as Thumbs_Up,
SUM(case when No_Solution_Found =1 then 1 else 0 end) as No_Solution,
SUM(case when Save is null then 0 else 1 end) as Total_Saves,
FROM table
GROUP BY NAME
Since only the Save column has NULLs, I assume that's the column you have the problem with.
In your query you wrote:
COUNT(case when Save is null then 0 else 1 end) as Total_Saves,
That is, you're replacing NULL by 0, which is a non null value and therefore is counted.
You presumable wanted to just write:
COUNT(Save) as Total_Saves
(And BTW, there is a comma after as Total_Saves in your query, that doesn't belong there, as no other column expression follows.)
Try the following query-:
Select
Name,
sum(Thumbs_up),
sum(No_Solution_Found),
count(case when [Save] is not null then 1 else null end) as Total_save
from TABLE
group by Name
SQL Server 2014

SQL Grouping entries with a different value

Let's assume I have a report that displays an ID and VALUE from different tables
| ID | VALUE |
|----|-------|
1 | 1 | 1 |
2 | 1 | 0 |
3 | 1 | 1 |
4 | 2 | 0 |
5 | 2 | 0 |
My goal is to display this table with grouped IDs and VALUEs. My rule to grouping VALUEs would be "If VALUE contains atleast one '1' then display '1' otherwise display '0'".
My current SQL is (simplified)
SELECT
TABLE_A.ID,
CASE
WHEN TABLE_B.VALUE = 1 OR TABLE_C.VALUE NOT IN (0,1,2,3)
THEN 1
ELSE 0
END AS VALUE
FROM TABLE_A, TABLE_B, TABLE_C
GROUP BY
TABLE_A.ID
(CASE
WHEN TABLE_B.VALUE = 1 OR TABLE_C.VALUE NOT IN (0,1,2,3)
THEN 1
ELSE 0
END)
The output is following
| ID | VALUE |
|----|-------|
1 | 1 | 1 |
2 | 1 | 0 |
3 | 2 | 0 |
Which is half way to the output I want
| ID | VALUE |
|----|-------|
1 | 1 | 1 |
2 | 2 | 0 |
So my Question is: How do I extend my current SQL (or change it completely) to get my desired output?
If you are having only 0 and 1 as distinct values in FOREIGN_VALUE column then using max() function as mentioned by HoneyBadger in the comment will fulfill your requirement.
SELECT
ID,
MAX(FOREIGN_VALUE) AS VALUE
FROM (SELECT
ID,
CASE WHEN FOREIGN_VALUE = 1
THEN 1
ELSE 0
END AS FOREIGN_VALUE
FROM TABLE,
FOREIGN_TABLE)
GROUP BY
ID;
Assuming value is always 0 or 1, you can do:
select id, max(value) as value
from t
group by id;
If value can take on other values:
select id,
max(case when value = 1 then 1 else 0 end) as value
from t
group by id;

SQL Pivot using count

I have a table which has the following entries
ID | column | value
------------------------
1 | status | DONE
2 | status | FAILED
1 | progress | Green
2 | progress | Red
i want the output as
ID | DONE | FAILED | GREEN | RED
1 | 1 | 0 | 1 | 0
2 | 0 | 1 | 0 | 1
Please let me know the query. I have tried pivot but not getting the results.
Here is a standard pivot query solution which does not use SQL Server's built in PIVOT capability:
SELECT ID,
SUM(CASE WHEN value = 'DONE' THEN 1 ELSE 0 END) AS DONE,
SUM(CASE WHEN value = 'FAILED' THEN 1 ELSE 0 END) AS FAILED,
SUM(CASE WHEN value = 'Green' THEN 1 ELSE 0 END) AS GREEN,
SUM(CASE WHEN value = 'Red' THEN 1 ELSE 0 END) AS RED
FROM yourTable
GROUP BY ID
SELECT *
FROM atable
PIVOT (
COUNT(column)
FOR value in ([DONE], [FAILED], [GREEN], [RED])
) p

SQL: query one column in same table

A football manager here. How do I:
Select all matches that have kicked-off but never had a goal.
Select all matches that kicked-off more than 1h ago but haven't yet had a goal or a corner-kick.
| Match | Event | EventTime |
|-------------------------------------------|
| 1 | Kick-off | 2014-12-15T16:00:00 |
| 1 | Throw-in | 2014-12-15T16:15:00 |
| 1 | Goal | 2014-12-15T16:20:00 |
| 1 | Corner-kick | 2014-12-15T16:30:00 |
| 1 | End | 2014-12-15T17:30:00 |
| 2 | Kick-off | 2014-12-10T16:00:00 |
| 2 | Goal | 2014-12-10T16:01:00 |
| 3 | Kick-off | 2014-12-05T08:00:00 |
| 3 | Corner-kick | 2014-12-05T08:10:00 |
I feel this should be simple, but I'm stuck somehow.
1:
SELECT DISTINCT Match
FROM dbo.YourTable A
WHERE [Event] = 'Kick-off'
AND NOT EXISTS( SELECT 1 FROM dbo.YourTable
WHERE Match = A.Match
AND [Event] = 'Goal')
2:
SELECT DISTINCT Match
FROM dbo.YourTable A
WHERE [Event] = 'Kick-off'
AND EventTime <= GETDATE(HOUR,-1,GETDATE())
AND NOT EXISTS( SELECT 1 FROM dbo.YourTable
WHERE Match = A.Match
AND [Event] IN ('Goal','Corner-kick'))
You would do this with aggregation and a having clause. For the first:
select match
from table t
group by match
having sum(case when event = 'Kick-off' then 1 else 0 end) > 0 and
sum(case when event = 'Goal' then 1 else 0 end) = 0;
For the second:
select match
from table t
group by match
having max(sum case when event = 'Kick-off' then eventtime end) <= getdate() - 1.0/24 and
sum(case when event in ('Goal', 'Corner-Kick') then 1 else 0 end) = 0;
Each condition in the having clause counts the number of rows that match the condition. > 0 means that at least one row matched. = 0 means no rows match.

SQL Query: Binary Fields on Dates for Time Series

I have a table that looks like the following:
ID | Date
1 | 2010-01-01
2 | 2010-02-01
3 | 2010-02-15
2 | 2010-02-15
4 | 2010-03-01
I am having trouble creating a table with the IDs as rows, and Time periods as columns. For a given time period, I would like to place a 1 if that ID has an associated date in that period, and a 0 if not.
So the output might look like:
ID | Jan-10 | Feb-10 | Mar-10
1 | 1 | 0 | 0
2 | 0 | 1 | 0
3 | 0 | 1 | 0
4 | 0 | 0 | 1
What is the best way to accomplish this?
I have created a new table containing all distinct IDs from the table above in anticipation of a join---but I'm not sure how to handle the 1/0s.
You can do this with a simple group by and conditional aggregation:
select id,
max(case when month(t.date) = 1 and year(t.date) = 2010 then 1 else 0 end) as "Jan-10",
max(case when month(t.date) = 2 and year(t.date) = 2010 then 1 else 0 end) as "Feb-10",
max(case when month(t.date) = 3 and year(t.date) = 2010 then 1 else 0 end) as "Mar-10"
from "table" t
group by id;
Because you have so many time periods, I would generate the code for the column using formulas in Excel (or your favorite spreadsheet).