I'm pretty new to SQL and am trying to figure out if there's a way to aggregate the date into new column. For instance, below is a sample set of date. I want to take all the type '2' and create new columns
Mem Balance Type New
1 2500 2 0
2 722 66 1
3 9422 1 0
4 122 2 1
5 788 66 1
So instead of having it like above, it would be like
Mem Type2Balance Type66Balance Type2New Type66New
1 2622 0 1 0
2 0 1510 0 2
Is there a way to do this in SQL? I thought maybe using IF statements within a case statement? I'm not asking for it to be done for me, more of looking for specifics that I can read about to make this happen. Thank you!
It seems like you want:
select
case when type = 2 then sum(balance) else 0 end type2balance,
case when type = 66 then sum(balance) else 0 end type66balance,
case when type = 2 then sum(new) else 0 end type2new,
case when type = 66 then sum(new) else 0 end type66new
from mytable
where type in (2, 66)
group by type
I am not sure what logic you want for column Mem in the resulset. It that's just a row number, then:
select
row_number() over(order by type) mem,
case when type = 2 then sum(balance) else 0 end type2balance,
case when type = 66 then sum(balance) else 0 end type66balance,
case when type = 2 then sum(new) else 0 end type2new,
case when type = 66 then sum(new) else 0 end type66new
from mytable
where type in (2, 66)
group by type
We could put the conditional expression on type inside the aggregate function, but it does not really make sense since you are grouping by type already. In that case, that would be:
select
row_number() over(order by type) mem,
sum(case when type = 2 then balance else 0 end) type2balance,
sum(case when type = 66 then balance else 0 end) type66balance,
sum(case when type = 2 then new else 0 end) type2new,
sum(case when type = 66 then new else 0 end) type66new
from mytable
where type in (2, 66)
group by type
With conditional aggregation:
select min(mem) mem,
sum(case when type = 2 then balance else 0 end) Type2Balance,
sum(case when type = 66 then balance else 0 end) Type66Balance,
sum(case when type = 2 then new else 0 end) Type2New,
sum(case when type = 66 then new else 0 end) Type66New
from tablename
where type in (2, 66)
group by type
See the demo.
Results:
| mem | Type2Balance | Type66Balance | Type2New | Type66New |
| --- | ------------ | ------------- | -------- | --------- |
| 1 | 2622 | 0 | 1 | 0 |
| 2 | 0 | 1510 | 0 | 2 |
Related
I want to get the total maximum number of column CODE which the maximum is defined by the last five digits from mybarcode column.
mybarcode | code | judge | create_date |
-------------+------+--------+-------------+
M71X400001 | 7 | pass |
M71X400002 | 7 | pass |
M71X400005 | 7 | pass |
M71X400010 | 7 | pass |
M81X400001 | 8 | pass |
M81X400002 | 8 | pass |
M81X400007 | 8 | pass |
M91X400001 | 9 | pass |
M91X400003 | 9 | pass |
```
Example:
>The maximum value of 7 from CODE column is 10 ( from M71X4'00010')
>The maximum value of 8 from CODE column is 7 ( from M81X4'00007')
>The maximum value of 9 from CODE column is 3 ( from M91X4'00003')
The result should be 10+7+3=20.
And want display in the result table below.
```
SELECT DAY,
SUM(CASE WHEN judge = 'pass' then 1 else 0 end) pass,
SUM(CASE WHEN judge = 'fail' then 1 else 0 end) fail
**??? as number**
from MYTABLE
where MONTH(create_date) = '04' and YEAR(create_date) = '2019'
GROUP BY DAY
Result Table
day | pass | fail | number |
--------+------+--------+----------+
1 | 9 | 0 | 20 |
2 | 9 | 0 | ?? |
3 | 9 | 0 | ?? |
I think you need to do group by two times. Please try below code -
For MySQL -
SELECT
DAY,
SUM(pass),
SUM(fail),
SUM(max_barcode)
FROM (
SELECT
DAY,
SUM(CASE WHEN judge = 'pass' then 1 else 0 end) pass,
SUM(CASE WHEN judge = 'fail' then 1 else 0 end) fail,
Code,
CAST(MAX(SUBSTRING(mybarcode, 5)) AS SIGNED) AS max_barcode
FROM MYTABLE
WHERE MONTH(create_date) = '%s' and YEAR(create_date) = '%s'
GROUP BY DAY, Code
) AS CTE
GROUP BY DAY;
FOR MS SQL Server -
;WITH CTE AS (
SELECT
DAY,
SUM(CASE WHEN judge = 'pass' then 1 else 0 end) pass,
SUM(CASE WHEN judge = 'fail' then 1 else 0 end) fail,
Code,
max_barcode = cast(max(right(mybarcode, 5)) as int)
FROM MYTABLE
WHERE MONTH(create_date) = '%s' and YEAR(create_date) = '%s'
GROUP BY DAY, Code
)
SELECT
DAY,
SUM(pass),
SUM(fail),
SUM(max_barcode)
FROM CTE
GROUP BY DAY;
I have a table with a "status" column which accepts a TINYINT. For example:
name | status
-------+--------
john | 0
joe | 1
johann | 0
jan | 1
jane | 0
How can I get a count of who is status 1 and who is status 0?
status1 | status0
--------+--------
2 | 3
Just use conditional aggregation:
select sum(status = 1) as status1, sum(status = 0) as status0
from t;
In your case, you could also write this as:
select sum(status) as status1, sum(1 - status) as status0
from t;
I would use a CASE statement to check for your value.
SELECT SUM(CASE WHEN [status] = 1 THEN 1 ELSE 0 END) AS Status1,
SUM(CASE WHEN [status] = 0 THEN 1 ELSE 0 END) AS Status0
FROM tbl;
I'm doing a SQL Union syntax and I wanted to have a result like this:
+---------------+-----+---------+
|trkBusinessUnit| New | Pending |
+---------------+-----+---------+
| AIIB 2 0 |
| Credit Control 1 3 |
| Direct Center 1 2 |
| Financial Ins 1 1 |
| Motor Acclaim 1 0 |
+-------------------------------+
from my code:
SELECT trkBusinessUnit, Count(*) as New,0 as Pending
FROM tblDTPTracker
WHERE trkStatus = 'New'
GROUP BY trkBusinessUnit
UNION
SELECT trkBusinessUnit,0 as New,Count(*) as Pending
FROM tblDTPTracker
WHERE trkStatus = 'Pending'
GROUP BY trkBusinessUnit
but then the current output is:
+---------------+-----+---------+
|trkBusinessUnit| New | Pending |
+---------------+-----+---------+
| AIIB 2 0 |
| Credit Control 1 0 |
| Credit Control 0 3 |
| Direct Center 1 0 |
| Direct Center 0 2 |
| Financial Ins 1 0 |
| Financial Ins 0 1 |
| Motor Acclaim 1 0 |
+-------------------------------+
Am I missing out something or doing something wrong? Kindly advise.
There are (or has been) some syntax issues in the previous answers, but the intent of both earlier answers is correct, you need to use a GROUP BY query and NOT use UNION - which simply does not do what you were hoping/expecting.
UNION or UNION ALL work ROW by ROW, and absolutely do NOT merge by COLUMN
So, the MySQL syntax for the group by based query could be any of these:
COUNT() using an implicit NULL
SELECT
trkBusinessUnit
, COUNT(CASE WHEN trkStatus = 'New' THEN 1 END) as New
, COUNT(CASE WHEN trkStatus = 'Pending' THEN 1 END) as Pending
FROM tblDTPTracker
GROUP BY trkBusinessUnit
;
COUNT() using explicit NULL
SELECT
trkBusinessUnit
, COUNT(CASE WHEN trkStatus = 'New' THEN 1 ELSE NULL END) as New
, COUNT(CASE WHEN trkStatus = 'Pending' THEN 1 ELSE NULL END) as Pending
FROM tblDTPTracker
GROUP BY trkBusinessUnit
;
SUM() as an alternative to counting:
select
trkBusinessUnit
, sum(case when trkStatus = 'New' then 1 else 0 end) as New
, sum(case when trkStatus = 'Pending' then 1 else 0 end) as Pending
from tblDTPTracker
where trkStatus in ('Pending', 'New')
group by trkBusinessUnit
;
Apologies to both Marc Gravell & Daniel Gadawski who preceded this answer; this answer is a derivative of yours.
See this SQLFiddle demo of these queries
If I understand you correctly, you don't have to use an union.
Try:
SELECT
trkBusinessUnit,
COUNT(CASE WHEN trkStatus = 'New' THEN 1 ELSE NULL END) as New,
COUNT(CASE WHEN trkStatus = 'Pending' THEN 1 ELSE NULL END) as Pending
FROM tblDTPTracker
GROUP BY trkBusinessUnit
Union appends rows vertically (noting that UNION also takes only the distinct rows; UNION ALL takes all rows). What you want is either a full outer join of two sub-queries, or a more complicated select. I'd go with the latter!
select tblDTPTracker,
sum(case trkStatus when 'New' then 1 else 0 end) as New,
sum(case trkStatus when 'Pending' then 1 else 0 end) as Pending
from tblDTPTracker
where trkStatus in ('Pending', 'New')
group by tblDTPTracker
The full outer join approach would be something like:
SELECT ISNULL(x.trkBusinessUnit, y.trkBusinessUnit) as trkBusinessUnit,
ISNULL(x.New, 0) as New,
ISNULL(y.Pending, 0) as Pending
FROM (
SELECT trkBusinessUnit, Count(1) as New
FROM tblDTPTracker
WHERE trkStatus = 'New'
GROUP BY trkBusinessUnit) x
FULL OUTER JOIN (
SELECT trkBusinessUnit, Count(1) as Pending
FROM tblDTPTracker
WHERE trkStatus = 'Pending'
GROUP BY trkBusinessUnit) y on y.trkBusinessUnit = x.trkBusinessUnit
cusID | Name | status | Date
---------------------------------
1 | AA | 0 | 2013-01-25
2 | BB | 1 | 2013-01-23
3 | CC | 1 | 2013-01-20
SELECT COUNT(cusID) FROM customer WHERE STATUS=0;
SELECT COUNT(cusID) FROM customer WHERE STATUS=1;
Is there a way of combing such two sql and return the results as one. Because want to avoid calling to DB everytime. I tried UNION of two statments, but only showing one result.
This is the shortest possible solution in MySQL.
SELECT SUM(status = 1) totalActive,
SUM(status = 0) totalInactive
FROM tableName
SQLFiddle Demo
and this is the CASE version
SELECT SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) totalActive,
SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) totalInactive
FROM tableName
SQLFiddle Demo
For the following Table, is it possible, to create an SQL Statement to create a data Matrix or view?
Table:
TeamA|TeamB|Won|Lost
--------------------
A | B | 5 | 3
A | C | 2 | 4
A | D | 9 | 1
B | E | 5 | 5
C | A | 2 | 4
Result-Matrix:
| A | B | C | D | E
----------------------------
A | 0 | 2 | -2 | 8 | 0
B | 0 | 0 | 0 | 0 | 0
C | -2 | 0 | 0 | 0 | 0
There are two ways that you can pivot data in MySQL. If you know the values ahead of time (teams) then you will hard-code the values or you can use a prepared statement to generate dynamic sql.
A static version would be:
select TeamA,
max(case when TeamB = 'A' then won - lost else 0 end) as A,
max(case when TeamB = 'B' then won - lost else 0 end) as B,
max(case when TeamB = 'C' then won - lost else 0 end) as C,
max(case when TeamB = 'D' then won - lost else 0 end) as D,
max(case when TeamB = 'E' then won - lost else 0 end) as E
from yourtable
group by TeamA;
See SQL Fiddle with Demo
If you want to use a dynamic version with a prepared statement, the code would be:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(CASE WHEN TeamB = ''',
TeamB,
''' THEN won - lost else 0 END) AS `',
TeamB, '`'
)
) INTO #sql
from
(
select *
from yourtable
order by teamb
) x;
SET #sql
= CONCAT('SELECT TeamA, ', #sql, '
from yourtable
group by TeamA');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
See SQL Fiddle with Demo.
Edit #1, after thinking about this I would actually do this a slight bit different. I would generate a true matrix os the data where the teams appeared in both the row and the column. To do this you would first use a UNION ALL query to get all teams in two columns:
select teama Team1, teamb Team2,
won-lost Total
from yourtable
union all
select teamb, teama,
won-lost
from yourtable
See SQL Fiddle with Demo. Once that is done, then you would pivot the data:
select Team1,
coalesce(max(case when Team2 = 'A' then Total end), 0) as A,
coalesce(max(case when Team2 = 'B' then Total end), 0) as B,
coalesce(max(case when Team2 = 'C' then Total end), 0) as C,
coalesce(max(case when Team2 = 'D' then Total end), 0) as D,
coalesce(max(case when Team2 = 'E' then Total end), 0) as E
from
(
select teama Team1, teamb Team2,
won-lost Total
from yourtable
union all
select teamb, teama,
won-lost
from yourtable
) src
group by Team1;
See SQL Fiddle with Demo. Which gives a more detailed result of:
| TEAM1 | A | B | C | D | E |
-------------------------------
| A | 0 | 2 | -2 | 8 | 0 |
| B | 2 | 0 | 0 | 0 | 0 |
| C | -2 | 0 | 0 | 0 | 0 |
| D | 8 | 0 | 0 | 0 | 0 |
| E | 0 | 0 | 0 | 0 | 0 |
You cannot create a SQL statement or view that has a variable number of columns. In standard SQL, you can pivot the data by doing something like:
select TeamA,
max(case when TeamB = 'A' then won - lost end) as A,
max(case when TeamB = 'B' then won - lost end) as B,
max(case when TeamB = 'C' then won - lost end) as C,
max(case when TeamB = 'D' then won - lost end) as D,
max(case when TeamB = 'E' then won - lost end) as E
from t
group by TeamA
order by 1
Some databases support a pivot statement.
To do this generically, you would have to create a SQL statement as a string, and then execute it (often called dynamic SQL). Such a statement could be produced by SQL, by a stored procedure, in Excel, or some other programming tool. It then would need to be executed.
Let me repeat: any given SQL statement has a pre-defined set of columns. You cannot vary the number of columns.