Counting distinct dates from two columns in a single SQL table - mysql

I've been reading through the solutions of similar problems posted here, but none seem to resolve my particular issue.
I currently have a table (CT_JOINED) that includes three columns: an identifer column (TUMOURID), a date column (AVCT_DATE) and another date column (OPDATE).
As an example, the columns for two IDs look as follows:
ID, AVCT_DATE, OPDATE
1, 06-APR-13, 06-APR-13
1, 06-APR-13, 14-JUN-13
1, 06-APR-13, 22-JUN-13
2, 03-APR-14, 10-DEC-15
2, 03-APR-14, 31-DEC-15
What I'm attempting to do is create a column that is equal to the number of unique dates per ID. So the result for ID 1 would be 3 and the result for ID 2 would be 3.
I have attempted a count of distinct values across the two columns, but this does not provide the answers above (it instead reports values of 3 and 2 respectively):
select TUMOURID, COUNT(DISTINCT(AVCT_DATE || OPDATE)) AS COUNT
FROM CT_JOINED
GROUP BY TUMOURID;
The same thing happens if I try and do the same in a new table:
CREATE TABLE CT_DISTINCT AS (
SELECT TUMOURID, COUNT(*) AS COUNT
FROM (
SELECT DISTINCT TUMOURID, AVCT_DATE, OPDATE
FROM CT_JOINED)
GROUP BY TUMOURID
);
I'm at a loss. Is it possible?

You could use:
SELECT TUMOURID, COUNT(DISTINCT d) AS cnt
FROM (select TUMOURID, AVCT_DATE AS d
FROM CT_JOINED
UNION ALL
SELECT TUMOURID, OPDATE AS d) sub
GROUP BY TUMOURID;

Unpivot the data and then use count(distinct) or remove duplicates along the way:
select tumourid, count(*)
from ((select tumourid, avct_date as dte
from ct_joined
) union -- intentional to remove duplicates
(select tumourid, opdate as dte
from ct_joined
)
) t
group by tumourid;

Use UNION to avoid duplicate date & just use count(*) :
SELECT tumourid, COUNT(date)
FROM ((SELECT tumourid, avct_date AS date
FROM ct_joined
) UNION
(SELECT tumourid, opdate
FROM ct_joined
)
) t
GROUP BY tumourid;

All of the answers below work like a charm with a few tweaks to also account for rows with null values. For instance:
SELECT TUMOURID, COUNT(*)
FROM ((SELECT TUMOURID, AVCT_DATE AS DTE
FROM CT_JOINED
WHERE AVCT_DATE IS NOT NULL
) UNION
(SELECT TUMOURID, OPDATE AS DTE
FROM CT_JOINED
WHERE OPDATE IS NOT NULL
)
) T
GROUP BY TUMOURID;
Many thanks.

Related

Add the result of SELECT query in another SELECT query

This is the result of a UNION of two SELECT
SELECT count(*) FROM
((SELECT session_id_current_user from test.tws_analytics
WHERE (add_date BETWEEN '2022-05-15' AND '2022-05-15') AND ((pathURL='vues/login.php' AND name_current_user='') OR (pathURL='' AND searchURL='?job=forgotten' AND name_current_user=''))
AND session_id_current_user NOT IN
(SELECT session_id_current_user from test.tws_analytics
WHERE (pathURL <> 'vues/login.php' AND searchURL <> '?job=forgotten') AND add_date BETWEEN '2022-05-15' AND '2022-05-15' order by session_id_current_user)
order by session_id_current_user)
UNION
(SELECT name_current_user from test.tws_analytics where add_date BETWEEN '2022-05-15' AND '2022-05-15' AND name_current_user IS NOT NULL AND name_current_user <> ''))
AS tem
The result is 11.
What I want to do is to select this result with other columns like this :
SELECT count(session),count(name), [AND tem.count(*)] FROM ....
This is the general idea, though i didn't know how to implement it.
a simplified general answer would be
select * from (select count(*) numsessions from sessions), (select count(*) numusers from users)
this will give 2 different counts, i didn't include the logics that you provided, but that will need to be done inside the 2 subqueries.

Ranking SUM of Value Column Grouped by Date

I have a query which I would like to add a ranking column. My existing query has three tables as a union query, with a sum of the total order value for that week. This query produces the sum of the total order value for that week, grouped by WeekCommencing, however I am struggling to add a ranking column based on the highest to the lowest total value for that week.
My (Updated) SQLFiddle example is here http://sqlfiddle.com/#!9/f1d43/35
CREATE and INSERT statements:
CREATE TABLE IF NOT EXISTS ORD (
WeekCommencing DATE,
Value DECIMAL(20 , 6 ),
Orders INT(6)
);
CREATE TABLE IF NOT EXISTS REF (
WeekCommencing DATE,
Value DECIMAL(20 , 6 ),
Orders INT(6)
);
CREATE TABLE IF NOT EXISTS SOH (
WeekCommencing DATE,
Value DECIMAL(20 , 6 ),
Orders INT(6)
);
INSERT INTO ORD (WeekCommencing, Value, Orders) VALUES
('2017-07-24',1,1),
('2017-07-31',2,1),
('2017-07-17',3,1);
INSERT INTO REF (WeekCommencing, Value, Orders) VALUES
('2017-07-24',4,1),
('2017-07-17',5,1),
('2017-07-31',6,1);
INSERT INTO SOH (WeekCommencing, Value, Orders) VALUES
('2017-07-17',7,1),
('2017-07-24',8,1),
('2017-07-31',9,1);
My best effort to date:
SELECT
WeekCommencing,
SUM(Value) AS 'TotalValue',
SUM(Orders) AS 'Orders',
#r:=#r+1 As 'Rank'
FROM
(SELECT
WeekCommencing, Value, Orders
FROM
ORD
GROUP BY WeekCommencing UNION ALL SELECT
WeekCommencing, Value, Orders
FROM
REF
GROUP BY WeekCommencing UNION ALL SELECT
WeekCommencing, Value, Orders
FROM
SOH
GROUP BY WeekCommencing) t1,
(SELECT #r:=0) Rank
GROUP BY WeekCommencing DESC;
My attempt currently ranks the order of week commencing, rather than the ranking highest to lowest.
My desired result is
WeekCommencing TotalValue Orders Rank
2017-07-31 17 3 1
2017-07-24 13 3 3
2017-07-17 15 3 2
Thanks is advance
SELECT a.*
, #i:=#i+1 rank
FROM
( SELECT weekcommencing
, SUM(value) totalvalue
, COUNT(*) totalorders
FROM
( SELECT weekcommencing, value, orders FROM ord
UNION ALL
SELECT weekcommencing, value, orders FROM ref
UNION ALL
SELECT weekcommencing, value, orders FROM soh
) x
GROUP
BY weekcommencing
) a
, (SELECT #i:=0) vars
ORDER
BY totalvalue DESC;

MySQL SELECT Query - Subtract a SUM() value with the combined total of two other SUM() values

I have two SELECT statements that give the values "TotalSales" and "VendorPay_Com". I want to be able to subtract VendorPay_Com from TotalSales within the one MySQL statement to get the value "Outstanding_Funds" but I haven't found a reliable way to do so.
These are my two statements:
Query 1:
SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold';
Query 2:
SELECT SUM(AC.Amount) AS VendorPay_Comm
FROM (
SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS `Amount` FROM COMMISSION AS C WHERE C.`status` = 'Paid') AS AC
Any help on this matter would be greatly appreciated :)
You can do it as follows :
select (select ...) - (select ...)
In your example, simply :
select
(
SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold'
)
-
(
SELECT SUM(AC.Amount) AS VendorPay_Comm
FROM (
SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS `Amount` FROM COMMISSION AS C WHERE C.`status` = 'Paid') AS AC
) AS Outstanding_Funds
Try
SELECT TotalSales-VendorPay_Comm AS Outstanding_Funds
FROM
(SELECT SUM(Price) AS TotalSales
FROM PROPERTY
WHERE Status = 'Sold') t1,
(SELECT SUM(Amount) AS VendorPay_Comm
FROM (SELECT Amount FROM lawyer_pays_vendor
UNION ALL
SELECT CommissionEarned AS Amount
FROM COMMISSION
WHERE Status = 'Paid') t0) t2
Here is sqlfiddle

MySQL; Get information from 3 table same time

People
here is my little problem.
I have three table:
a_names_1
b_names_2
c_names_3
they are same by structure. all of them has two item: name and used
Is there any QUERY to run to get and count all the 'name' that has 'used'=1 from all those three tables together.
I've tried this one, but didn't work:
(SELECT COUNT(*) 'name' from a_names_1) UNION
(SELECT COUNT(*) 'name' from a_names_2) UNION
(SELECT COUNT(*) 'name' from a_names_3) WHERE `used`=1
I'm using PHPMyAdmin for MySQL.
Any Help would be appreciated.. thanks in advance
This query outputs count of distinct names from all tables with used=1
select count(distinct name)
from
(
select name,used from a_names_1 where used=1
union all
select name,used from a_names_2 where used=1
union all
select name,used from a_names_3 where used=1
) t
If you need to SUM all USED for each NAME from all tables and output only with SUM of used=1 then:
select count(*) from
(
select name, SUM(used)
from
(
select name,used from a_names_1
union all
select name,used from a_names_2
union all
select name,used from a_names_3
) t
GROUP BY name
HAVING SUM(used)=1
) t1
select count(*) as name
from
(
select name, used from a_names_1
union
select name, used from a_names_2
union
select name, used from a_names_3) t
where t.used = 1
Probably this is slow, because you lose the index optimizations. What I would do is do the three queries, something like
SELECT SUM('name') AS name_sum
FROM ((SELECT COUNT(*) 'name' from a_names_1 WHERE `used`=1)
UNION (SELECT COUNT(*) 'name' from a_names_2 WHERE `used`=1));
If this doesn't work, it is probably a problem with the usage of name
Maybe you wanted this way:
select count(*) as cnt
from
(
select name from a_names_1 t1 where t1.used = 1
union
select name from a_names_2 t2 where t2.used = 1
union
select name from a_names_3 t3 where t3.used = 1
) t
The straight forward solution;
SELECT SUM(used) FROM (
SELECT used FROM a_names_1 WHERE used=1
UNION ALL
SELECT used FROM a_names_2 WHERE used=1
UNION ALL
SELECT used FROM a_names_3 WHERE used=1
) a
SQLfiddle for testing
An alternative if you have an index on used (and the only values of used are 0 or 1) is to just do the counting using the index;
SELECT SUM(used) total FROM (
SELECT SUM(used) used FROM a_names_1
UNION ALL
SELECT SUM(used) FROM a_names_2
UNION ALL
SELECT SUM(used) FROM a_names_3
) a
SQLfiddle for this example.
If you look at the query plan of the latter query, you can see it uses the indexes effectively.

mysql self join

I have a table called receiving with 4 columns:
id, date, volume, volume_units
The volume units are always stored as a value of either "Lbs" or "Gals".
I am trying to write an SQL query to get the sum of the volumes in Lbs and Gals for a specific date range. Something along the lines of: (which doesn't work)
SELECT sum(p1.volume) as lbs,
p1.volume_units,
sum(p2.volume) as gals,
p2.volume_units
FROM receiving as p1, receiving as p2
where p1.volume_units = 'Lbs'
and p2.volume_units = 'Gals'
and p1.date between "2012-01-01" and "2012-03-07"
and p2.date between "2012-01-01" and "2012-03-07"
When I run these queries separately the results are way off. I know the join is wrong here, but I don't know what I am doing wrong to fix it.
SELECT SUM(volume) AS total_sum,
volume_units
FROM receiving
WHERE `date` BETWEEN '2012-01-01'
AND '2012-03-07'
GROUP BY volume_units
You can achieve this in one query by using IF(condition,then,else) within the SUM:
SELECT SUM(IF(volume_units="Lbs",volume,0)) as lbs,
SUM(IF(volume_units="Gals",volume,0)) as gals,
FROM receiving
WHERE `date` between "2012-01-01" and "2012-03-07"
This only adds volume if it is of the right unit.
This query will display the totals for each ID.
SELECT s.`id`,
CONCAT(s.TotalLbsVolume, ' ', 'lbs') as TotalLBS,
CONCAT(s.TotalGalVolume, ' ', 'gals') as TotalGAL
FROM
(
SELECT `id`, SUM(`volume`) as TotalLbsVolume
FROM Receiving a INNER JOIN
(
SELECT `id`, SUM(`volume`) as TotalGalVolume
FROM Receiving
WHERE (volume_units = 'Gals') AND
(`date` between '2012-01-01' and '2012-03-07')
GROUP BY `id`
) b ON a.`id` = b.`id`
WHERE (volume_units = 'Lbs') AND
(`date` between '2012-01-01' and '2012-03-07')
GROUP BY `id`
) s
this is a cross join with no visible condition on the join, i don't think you meant that
if you want to sum quantities you don't need to join at all, just group as zerkms did
You can simply group by date and volume_units without self-join.
SELECT date, volume_units, sum(volume) sum_vol
FROM receving
WHERE date between "2012-01-01" and "2012-03-07"
GROUP BY date, volume_units
Sample test:
select d, vol_units, sum(vol) sum_vol
from
(
select 1 id, '2012-03-07' d, 1 vol, 'lbs' vol_units
union
select 2 id, '2012-03-07' d, 2 vol, 'Gals' vol_units
union
select 3 id, '2012-03-08' d, 1 vol, 'lbs' vol_units
union
select 4 id, '2012-03-08' d, 2 vol, 'Gals' vol_units
union
select 5 id, '2012-03-07' d, 10 vol, 'lbs' vol_units
) t
group by d, vol_units