Combine query for sum of two tables with date - mysql

I have two tables like following
challenge_table
Challenger chdate
----------------------
abc 11-02-2012
aaa 12-02-2012
ccc 12-02-2012
bbb 13-02-2012
ddd 14-02-2012
init_table
Initiateid indate
----------------------
a1 11-02-2012
a2 11-02-2012
a3 12-02-2012
a4 13-02-2012
a5 13-02-2012
I need a result like this
challengecount initcount curdate
-----------------------------------
1 2 11-02-2012
2 1 12-02-2012
1 2 13-02-2012
1 0 14-02-2012
i tried a query like this
SELECT COUNT(*) challengecount, chdate caldate FROM challenge_table
UNION ALL
SELECT COUNT(*) Initiatecount, indate caldate FROM init_table
But it doesn't work for me.

Since MySQL does not support a FULL OUTER JOIN, you need to combine the 2 tables with a UNION.
Then group by the date and count the values of the 2 tables
select caldate, count(distinct Challenger), count(distinct Initiateid)
from
(
SELECT Challenger, null as Initiateid, chdate as caldate FROM challenge_table
UNION ALL
SELECT null, Initiateid, indate FROM init_table
) tmp
group by caldate

Related

MySQL count number of times a result appears after grouping

I have a very similar problem to this one:
Count unique occurrences per each distinct variable in MySQL but with a twist.
I'm working with a select statement that shows results much like what the above-mentioned question does.
If I boil down my statement into a simple form for this question my code looks like this:
SELECT
salesman,
brand
FROM
sales
WHERE
sales.date=something
GROUP BY salesman, brand
Resulting in an example output like this:
salesman brand
____ _______
Mark aaa
Mark bbb
Mark ccc
Mark ddd
Jane aaa
Jane bbb
Cody aaa
Without the GROUP BY part the results might look like this:
salesman brand
____ _______
Mark ddd
Jane bbb
Mark aaa
Cody aaa
Mark ddd
Jane aaa
Mark aaa
Jane aaa
Mark ccc
Mark bbb
The twist I have is that I want to count the number of times each brand appears after the grouping and output it in the same table of results.
EG:
salesman brand brand_count
____ _______ _____
Mark aaa 3
Mark bbb 2
Mark ccc 1
Mark ddd 1
Jane aaa 3
Jane bbb 2
Cody aaa 3
I've tried adding count(*) to the SELECT but that only returns the number 2 for salesman Mark with brand aaa and 1 for Cody, which isn't what I'm after.
I want to show for each brand the number of times it appeared in the results.
So brand aaa for example shows 3 times.
I suspect there might be a subquery needed though I'm not sure how it would work.
Any suggestions would be greatly appreciated.
EDIT:
Original MySQL code below in case it helps
select
ARM.SALESMAN AS 'SalesmanNumber',
INM.BRAND AS 'Brand'
from
ARMASTER ARM
LEFT JOIN ARTRAN ART ON ARM.NUMBER = ART.CUST_NO
LEFT JOIN INTRAN INTR ON ART.REF = INTR.REF
LEFT JOIN ARSALECD SALESMAN ON ARM.SALESMAN = SALESMAN.CODE
LEFT JOIN INMASTER INM ON INTR.STOCK_CODE = INM.CODE
where
ARM.AREA = 01
AND ARM.CUSTTYPE <> '99'
AND ARM.SALESMAN NOT IN (24,48,49,50,51,52,71,72,74,90)
AND (
(YEAR(INTR.DATE) = YEAR(#mth) AND MONTH(INTR.DATE) = MONTH(#mth))
OR (YEAR(DATE_ADD(#mth, INTERVAL -1 MONTH)) AND MONTH(INTR.DATE) = MONTH(DATE_ADD(#mth, INTERVAL -1 MONTH)))
OR (YEAR(DATE_ADD(#mth, INTERVAL -2 MONTH)) AND MONTH(INTR.DATE) = MONTH(DATE_ADD(#mth, INTERVAL -2 MONTH)))
)
group by Brand , SalesmanNumber;
I tried making the select part of the statement look like this per Robo suggestion:
ARM.SALESMAN AS 'SalesmanNumber',
INM.BRAND AS 'Brand',
(
SELECT
count(*)
FROM
INMASTER AS s
WHERE
s.BRAND=INMASTER.BRAND
) AS brand_count
But get this error
Error Code: 1054. Unknown column 'INMASTER.BRAND' in 'where clause'
Also, I'm working with an old database version: MySQL 5.1.60
On an older MySQL version you can use:
select s.salesman,s.brand,brand_count
from sales s
inner join (select brand,count(brand) as brand_count
from ( select salesman,brand
from sales
group by salesman,brand
) as tbl
group by brand
) as x on x.brand=s.brand
group by salesman,brand,brand_count
order by s.salesman ;
https://dbfiddle.uk/EevII2mZ
Group by the result , in an outer query count the brand and then use that as a subquery to join with the primary same table
You need to use a subquery:
SELECT
salesman,
brand,
(
SELECT
count(*)
FROM
sales AS s
WHERE
s.brand=sales.brand
) AS brand_count
FROM
sales
WHERE
sales.date=something
GROUP BY salesman, brand
On MySQL v8+, you can use COUNT() OVER () function.
Create table & data example:
CREATE TABLE sales(
salesman VARCHAR(255),
brand VARCHAR(255),
date DATE);
INSERT INTO sales VALUES
('Mark','ddd','2022-10-06'),
('Jane','bbb','2022-10-06'),
('Mark','aaa','2022-10-06'),
('Cody','aaa','2022-10-06'),
('Mark','ddd','2022-10-06'),
('Jane','aaa','2022-10-06'),
('Mark','aaa','2022-10-06'),
('Jane','aaa','2022-10-06'),
('Mark','ccc','2022-10-06'),
('Mark','bbb','2022-10-06');
Query:
SELECT
salesman,
brand,
COUNT(brand) OVER (PARTITION BY Brand) AS brand_count
FROM
sales
WHERE date='2022-10-06'
GROUP BY salesman, brand
ORDER BY salesman DESC, brand
Results:
salesman
brand
brand_count
Mark
aaa
3
Mark
bbb
2
Mark
ccc
1
Mark
ddd
1
Jane
aaa
3
Jane
bbb
2
Cody
aaa
3
Demo fiddle
For older MySQL version:
SELECT t1.salesman, t1.brand, brand_count
FROM sales t1
JOIN
/*this part of the query is just to get the brand_count*/
(SELECT brand, COUNT(*) AS brand_count
FROM
(SELECT salesman, brand
FROM sales
WHERE date='2022-10-06'
GROUP BY salesman, brand) t
GROUP BY brand) t2
/*this part of the query is just to get the brand_count*/
ON t1.brand=t2.brand
WHERE t1.date='2022-10-06'
GROUP BY t1.salesman, t1.brand
ORDER BY t1.salesman DESC, t1.brand;
Demo fiddle

How to get the output as following by combining data from 3 different tables

so I have 3 tables in my db, where all 3 tables contains a column which have similar data, but name of that column is different on all the 3 tables, below is an example.
Ban Table
user_id
ban_user_id
ban_date
reason
end_date
1300
1
xyz
xyz
xyz
32
1
xyz
xyz
xyz
43
2
xyz
xyz
xyz
Reports Table
user_id
last_modified_user_id
report_date
reason
end_date
1300
1
xyz
xyz
xyz
32
2
xyz
xyz
xyz
43
2
xyz
xyz
xyz
Warning Table
user_id
warning_user_id
warning_date
reason
end_date
1300
1
xyz
xyz
xyz
32
2
xyz
xyz
xyz
43
3
xyz
xyz
xyz
Now I want to fetch data by combining these 3 tables, where ban_user_id, last_modified_user_id, and warning_user_id contains the data of staff member who took the actions, so i want to group the data by the staff id.
The output i am looking for is as follows:
staff_id
total_reports
total_bans
total_warnings
1
1
2
1
2
2
1
1
3
0
0
1
where it is counting the data for each table by grouping the 2nd column, ban_user_id, last_modified_user_id, warning_user_id respectively. And than combining the data.
I tried things with UNION All and stuffs, but it didn't work out.
Thankyou in advance for your help
Use UNION ALL for all 3 tables and then aggregate:
SELECT staff_id,
COUNT(report) AS total_reports,
COUNT(ban) AS total_bans,
COUNT(warning) AS total_warnings
FROM (
SELECT last_modified_user_id AS staff_id, 1 AS report, null AS ban, null AS warning FROM Reports
UNION ALL
SELECT ban_user_id, null, 1, null FROM Ban
UNION ALL
SELECT warning_user_id, null, null, 1 FROM Warning
) t
GROUP BY staff_id;
Or:
SELECT staff_id,
SUM(report) AS total_reports,
SUM(ban) AS total_bans,
SUM(warning) AS total_warnings
FROM (
SELECT last_modified_user_id AS staff_id, 1 AS report, 0 AS ban, 0 AS warning FROM Reports
UNION ALL
SELECT ban_user_id, 0, 1, 0 FROM Ban
UNION ALL
SELECT warning_user_id, 0, 0, 1 FROM Warning
) t
GROUP BY staff_id;
See the demo.
You can use Table joins (Inner/outer/left/right) to get the data instead of union.
I'm assuming the staff_id is the equivalent of user_id column as you haven't mentioned anything about that, so your script will look something like this:
SELECT W.user_id AS staff_id,
B.ban_user_id,
R.last_modified_user_id,
W.warning_user_id
FROM Warning AS W
LEFT JOIN Reports AS R on R.user_id = W.user_id
LEFT JOIN Ban AS B on B.user_id = W.user_id
group by W.user_id

Use a sub query result

I have a table with numbers and dates (1 number each date and dates aren't necessarily at regular intervals).
I would like to get the count of dates when a number isn't in the table.
Where I am :
select *
from
(
select
date from nums
where chiffre=1
order by date desc
limit 2
) as f
I get this :
date
--------------
2014-09-07
--------------
2014-07-26
Basically, I have this query dynamically:
select * from nums where date between "2014-07-26" and "2014-09-07"
And in a second time, browse the whole table (because there I limited to the first 2 rows but I would compare the 2 and 3 and 3 and 4 etc...)
The goal is to get this:
date | actual_number_of_real_dates_between_two_given_dates
2014-09-07 - 2014-07-26 | 20
2014-04-02 - 2014-02-12 | 13
etc...
How can I do this? Thanks.
Edit:
What I have (just an example, dates and "chiffre" are more complex) :
date | chiffre
2014-09-30 | 2
2014-09-29 | 1
2014-09-28 | 2
2014-09-27 | 2
2014-09-26 | 1
2014-09-25 | 2
2014-09-24 | 2
etc...
What I need for the number "1":
actual_number_of_real_dates_between_two_given_dates
1
3
etc...
Edit 2:
My updated query thanks to Gordon Linoff
select count(n.id) as difference
from nums n inner join
(select min(date) as d1, max(date) as d2
from (select date from nums where chiffre=1 order by date desc limit 2) d
) dd
where n.date between dd.d1 and dd.d2
How can I test row 2 with 3? 3 with 4 etc... Not only last 2?
Should I use a loop? Or I can do it without?
Does this do what you want?
select count(distinct n.date) as numDates,
(datediff(dd.d2, dd.d1) + 1) as datesInPeriod,
(datediff(dd.d2, dd.d1) + 1 - count(distinct n.date)) as missingDates
from nums n cross join
(select date('2014-07-26') as d1, date('2014-09-07') as d2) d
where n.date between dd.d1 and dd.d2;
EDIT:
If you just want the last two dates:
select count(distinct n.date) as numDates,
(datediff(dd.d2, dd.d1) + 1) as datesInPeriod,
(datediff(dd.d2, dd.d1) + 1 - count(distinct n.date)) as missingDates
from nums n cross join
(select min(date) as d1, max(date) as d2
from (select date from nums order by date desc limit 2) d
) dd
where n.date between dd.d1 and dd.d2;

How to write mysql query for fetching data from 2 sql query?

I have 2 tables
tbltraining
trId(PK) trname
------- ------
1 training1
2 training2
3 training3
4 training4
5 training5
6 training6
tbltrainAssign
trassigno trId(FK) date1 date2
--------- ------ ----------- ----------
1 1 12/12/2012 12/12/2013
1 1 12/12/2012 12/12/2013
2 3 01/12/2012 08/12/2013
2 3 01/12/2012 08/12/2013
2 3 01/12/2012 08/12/2013
3 1 02/12/2012 12/12/2013
3 1 12/12/2012 12/12/2013
what i want is the data from tbltraining with the count of assignments. trId =1 is assigned 2 times and trId is assigned 1tim in tbltrainAssign . so the result should look like
trId trName count
1 training1 2
2 training2 0
3 training3 1
4 training4 0
5 training5 0
6 training6 0
What you need is a simple, straightforward, JOIN especially LEFT JOIN to get unmatched trNames that had no assignment in the second table, with COUNT and a GROUP BY like so:
SELECT t.trId, t.trname, COUNT(s.trId)
FROM tbltraining t
LEFT JOIN tbltrainAssign s ON t.trId = s.trId
GROUP BY t.trId, t.trname;
SQL Fiddle Demo
Side not: Please avoid descriptive prefixes that you are using in the tables' names and the columns' names the tbl and the tr.
Update: You have to select the distinct dates from the assignment table in order to count the distinct assignments for each training like so:
SELECT t.trId, t.trname, COUNT(s.trId)
FROM tbltraining t
LEFT JOIN
(
SELECT DISTINCT trId, DATE(date1), date(date2)
FROM tbltrainAssign
) s ON t.trId = s.trId
GROUP BY t.trId, t.trname;
Updated SQL Fiddle Demo
select a.trId trId,a.trName trName,count(distinct b.trssigno) count
from tbltraining a, tbltrainAssign b
where a.trId=b.trId
group trId,trName
order by trId
this will give the desired result
select t.trId, t.trname, count(t.trassigno) from (
select tb.trId, tb.trname, ta.trassigno from tbltrainAssign ta
inner join tbltraining tb on ta.trId=tb.trId
) t
group by t.trId, t.trname

Mysql Grouping and Counting

i have a 3 Tables:
1 TableTraders
trader_id|Domain|
---------------------
1|google.com
2|yahoo.com
2 Table Counter_in
counter_time counter_ip counter_domain_id
111111 222222 1
111111 222224 2
111111 222225 3
111111 222232 2
111111 222221 3
111111 222223 4
1111311 22223422 5
3 Table Out Counter
counter_time counter_ip counter_domain_id
111111 222222 1
111111 222222 2
111111 222222 3
111111 222226 2
111111 222221 3
111111 222222 4
1309351485 2130708581 5
1309351485 2130708581 4
1309710116 2130706433 4
1309351485 2130708581 1
1309710274 2130706433 1
Ok what i want todo is join the tables 1 , 2 , 3 and group them together, and count them.
trader_id|DOMAIN|IN|OUT
--------------------------
1|google.com|3|1
2|yahoo.com|1|2
I tried many things, but i get always wrong results. How do i join right the queries that i get results i want
*EDIT
The query attempted:
SELECT traders.trader_id, traders.domain, COUNT( counter_in.counter_domain_id ) AS today_in, COUNT( counter_out.counter_domain_id ) AS today_out
FROM traders
JOIN counter_in ON traders.trader_id = counter_in.counter_domain_id
JOIN counter_out ON traders.trader_id = counter_out.counter_domain_id
GROUP BY traders.trader_id, traders.domain
LIMIT 0 , 30
Results:
trader_id domain today_in today_out
1 bing.com 3 3
2 google.com 4 4
3 yahoo.com 4 4
4 msn.com 3 3
5 yandex.com 1 1
SELECT
TableTraders.trader_id,
TableTraders.Domain,
COUNT(TableIn.trader_id) AS in_count,
COUNT(TableOut.trader_id) AS out_count
FROM TableTraders
JOIN TableIn ON TableTraders.trader_id = TableIn.trader_id
JOIN TableOut ON TableTraders.trader_id = TableOut.trader_id
GROUP BY TableTraders.trader_id, TableTraders.Domain
Not certain what your table names are from your example above, since they contain spaces. Substitute the correct table names.
It appears the other answer may be giving you some sort of Cartesian result thus duplicating results. Take your traders and join to distinct sub-query counts from respective in / out tables.
SELECT
TT.trader_id,
TT.Domain,
TIN.InCount,
TOUT.OutCount
FROM
TableTraders TT
LEFT Join ( select Trader_ID, count(*) as InCount
from TableIn
group by Trader_ID ) TIN
on TT.Trader_ID = TIN.Trader_ID
LEFT Join ( select Trader_ID, count(*) as InCount
from TableOut
group by Trader_ID ) TOUT
on TT.Trader_ID = TOUT.Trader_ID
If you want it by DISTINCT IP address per in/out, just change
COUNT(*)
to
COUNT( Distinct IP )