join results of two mysql queries on the same table - mysql

I have the intuition that I'm missing something simple, so please excuse me if it's a stupid question but I haven't been able to find an answer here.
I'm treating a database with usage behaviors. We have one row per user, with date and time spent (plus other non-relevant info).
I'd like to output a histogram of the number of visits per day, and number of visits that lasted more than a certain time ; ideally I'd like to have that in one query.
For now I have these two queries:
SELECT DATE(date), COUNT(date) AS Number_of_users FROM users GROUP BY DATE(date)
SELECT DATE(date), COUNT(date) AS Number_of_stayers FROM users WHERE timespent>5 GROUP BY DATE(date)
How can I combine them to obtain a result in the form of:
date users stayers
2014-01-01 21 5
2014-01-02 13 0
etc.
Thanks in advance for any help!

You can try using IF, like this:
SELECT DATE(date),
COUNT(date) AS Number_of_users,
SUM(IF(timespent>5,1,0)) AS Number_of_stayers
FROM users
GROUP BY DATE(date)

This should work, or at least show the basic idea of using JOINs:
SELECT DATE(a.date),
COUNT(a.date) AS Number_of_users,
COUNT(b.date) AS Number_of_stayers
FROM users a
LEFT JOIN users b ON (a.date = b.date AND b.timespent>5)

Related

Growth for each quarter+year in SQL over my user table

I am using MYSQL and I have a User database table where my registered users are stored. I'd love to see how many users have registered on an increasing timeline for each quarter. So maybe Q1 2016 I had 1000 users total, then in Q2 2016 I had 2000 users register, in Q3 2016 4000 total users registered, etc (so I want to see the increase, not just how many registered in each quarter)
From another Stack Overflow post, I was able to create a query to see it by each day:
select u.created, count(*)
from (select distinct date(DateCreated) created from `Users`) u
join `Users` u2 on u.created >= date(u2.DateCreated)
group by u.created
and this works for each day, but I'd like to now group it by quarter and year. I tried using the QUARTER(d) function in mysql and even QUARTER(d) + YEAR(d) to concat it but I still can't get the data right (The count(*) ends up producing incredibly high values).
Would anyone be able to help me get my data grouped by quarter/year? My timestamp column is called DateCreated (it's a unix timestamp in milliseconds, so I have to divide by 1000 too)
Thanks so much
I would suggest using a correlated subquery -- this allows you to easily define each row in the result set. I think this is the logic that you want:
select dates.yyyy, dates.q,
(select count(*)
from Users u
where u.DateCreated < dates.mindc + interval 3 month
) as cnt
from (select year(DateCreated) as yyyy, quarter(DateCreated) as q
min(DateCreated) as mindc
from Users u
group by year(DateCreated), quarter(DateCreated)
) dates;

sql query doesn't give me all the months

I have a "customers" table with many columns. I need to use only two of them. date(the date that the customer was registerd), referrer( how did the customer find us: google or facebook or friends). I need for each month to show how many customers added by each referrer. for example: 2016-8 4 customers by facebook, 10 customers by friends and 13 customers by google). of course it should give me for each month the result in the example.
I tried this query - but it doesn't give me all the months only 2 of the months and one of them is being shown twice. can someone please review my query?
SELECT referrer,date, COUNT(`date`)
FROM `customers`
GROUP BY `referrer`;
Try this:
SELECT referrer,date, COUNT(date)
FROM customers
GROUP BY Year(date), MONTH(date), referrer;
If you want to select the output for a certain year you can try this:
SELECT referrer,date, COUNT(date)
FROM customers
WHERE record_date.YEAR = 2016
GROUP BY Year(date), MONTH(date), referrer;

Find a column with one value for 2 different dates

I have the following table:
table 1
columns are as following:
date , time , user_id , channel
I wish to find for a list of USERS watching in 2 different DATES , channel(lets say CNN, NBC...) all the entries relevant.
Means the channel in DATE 1 and DATE 2 is the same, also the user_id.
I try allready following:
select distinct monthname(date),max(date), min(date) count(distinct user_id)
from iptv_clean
group by monthname(date)
having min(date)!= max(date)
But it seems not to work well.
Any ideas?
The following gives a list of users and channels that users watched on more than one date:
select user_id, channel, count(distinct date)
from iptv_clean
group by user_id, channel
having count(distinct date) > 1;
Is this what you want?

How can I write a query that aggregate a single row with latest date among multiple set of rows?

I have a MySQL table where there are many rows for each person, and I want to write a query which aggregates rows with special constraint. (one per person)
For example, lets say the table is consist of following data.
name date reason
---------------------------------------
John 2013-04-01 14:00:00 Vacation
John 2013-03-31 18:00:00 Sick
Ted 2012-05-06 20:00:00 Sick
Ted 2012-02-20 01:00:00 Vacation
John 2011-12-21 00:00:00 Sick
Bob 2011-04-02 20:00:00 Sick
I want to see the distribution of 'reason' column. If I just write a query like below
select reason, count(*) as count from table group by reason
then I will be able to see number of reasons for this table overall.
reason count
------------------
Sick 4
Vacation 2
However, I am only interested in single reason from each person. The reason that should be counted should be from a row with latest date from the person's records. For example, John's latest reason would be Vacation while Ted's latest reason would be Sick. And Bob's latest reason (and the only reason) is Sick.
The expected result for that query should be like below. (Sum of count will be 3 because there are only 3 people)
reason count
-----------------
Sick 2
Vacation 1
Is it possible to write a query such that single latest reason will be counted when I want to see distribution(count) of reasons?
Here are some facts about the table.
The table has tens of millions of rows
For most of times, each person has one reason.
Some people have multiple reasons, but 99.99% of people have fewer than 5 reasons.
There are about 30 different reasons while there are millions of distinct names.
The table is partitioned based on date range.
SELECT T.REASON, COUNT(*)
FROM
(
SELECT PERSON, MAX(DATE) AS MAX_DATE
FROM TABLE-NAME
GROUP BY PERSON
) A, TABLE-NAME T
WHERE T.PERSON = A.PERSON AND T.DATE = A.MAX_DATE
GROUP BY T.REASON
Try this
select reason, count(*) from
(select reason from table where date in
(select max(date) from table group by name)) t
group by reason
In MySQL, it's not very efficient to do this kind of query since you don't have access to tools like partitionning query in SQL Server or Oracle.
You can still emulate it by doing a subquery and retrieve the rows based on the condition you need, here the maximum date :
SELECT t.reason, COUNT(1)
FROM
(
SELECT name, MAX(adate) AS maxDate
FROM #aTable
GROUP BY name
) maxDateRows
INNER JOIN #aTable t ON maxDateRows.name = t.name
AND maxDateRows.maxDate = t.adate
GROUP BY t.reason
You can see a sample here.
Test this query on your samples, but I'm afraid that it will be slow as hell.
For your information, you can do the same thing in a more elegant and much much faster way in SQL Server :
SELECT reason, COUNT(1)
FROM
(
SELECT name
, reason
, RANK() OVER(PARTITION BY name ORDER BY adate DESC) as Rank
FROM #aTable
) AS rankTable
WHERE Rank = 1
GROUP BY reason
The sample is here
If you are really stuck to MySql, and the first query is too slow, then you can split the problem.
Do a first query creating a table:
CREATE TABLE maxDateRows AS
SELECT name, MAX(adate) AS maxDate
FROM #aTable
GROUP BY name
Then create index on both name and maxDate.
Finally, get the results :
SELECT t.reason, COUNT(1)
FROM maxDateRows m
INNER JOIN #aTable t ON m.name = t.name
AND m.maxDate = t.adate
GROUP BY t.reason
The solution you are looking for seems to be solved by this query :
select
reason,
count(*)
from (select * from tablename group by name) abc
group by
reason
It is quite fast and simple. You can view the SQL Fiddle
Apologies if this answer duplicates an existing. Maybe I'm suffering from some form aphasia but I cannot see it...
SELECT x.reason
, COUNT(*)
FROM absentism x
JOIN
( SELECT name,MAX(date) max_date FROM absentism GROUP BY name) y
ON y.name = x.name
AND y.max_date = x.date
GROUP
BY reason;

MySQL Select multiple distinct

I have one table which holds lots of records. Its for an auction site. This table can have multiple user_id which can be the same and multiple auction_id which can be the same.
I am trying to write a script that sends an email once to each user that has placed a bid. If a user places say 10 bids on the same auction, I only want the email to be sent once per user per auction, per bid.
How would I do this with distinct over 2 fields? The user_id field and the auction_listing field? I will also need to have a WHERE clause so I only select records of auctions that have less than 24 hours to run.
SELECT DISTINCT b.user_id, b.auction_listing
FROM AuctionBids b
JOIN Auctions a USING (auction_listing)
WHERE a.end_datetime < NOW() + INTERVAL 24 hour
Or
SELECT b.user_id, b.auction_listing
FROM AuctionBids b
JOIN Auctions a USING (auction_listing)
WHERE a.end_datetime < NOW() + INTERVAL 24 hour
GROUP BY b.user_id, b.auction_listing
Without knowing your table schema it is hard to answer to answer you question.
In general if you do a GROUP_BY user_id in the end one user will only appear once in your query results