Get the average attendance? - subquery

I am trying to develop a subquery to get the average attendance from two tables along with full details

select EVENTID ,
EVENTNAME ,
STARTDATETIME ,
ENDDATETIME ,
CONCERT_CONCERTID ,
VENUE_VENUEID,COUNT(TIMEOFARRIVAL),AVG(TIMEOFARRIVAL)
FROM EVENT INNER JOIN BOOKING ON BOOKING.EVENT_EVENTID = EVENT.EVENTID;
There is an error inconsistent datatypes expected number got timestamp

Your first step is to get the number of attendees per event:
SELECT e.eventid, COUNT(b.customer_customerid) AS customer_cnt
FROM event e LEFT JOIN booking b
ON e.eventid = b.event_eventid
GROUP BY e.eventid;
Now I use a LEFT JOIN above because an event could conceivably have zero attendance and those should be counted as well!
We can get the average using a window function (what Oracle calls an analytic function):
SELECT eventid, attendance, AVG(attendance) OVER ( ) AS avg_attendance
FROM (
SELECT e.eventid, COUNT(b.customer_customerid) AS attendance
FROM event e LEFT JOIN booking b
ON e.eventid = b.event_eventid
GROUP BY e.eventid
);
Now we can get all events with below-average attendance:
SELECT eventid, attendance FROM (
SELECT eventid, attendance, AVG(attendance) OVER ( ) AS avg_attendance
FROM (
SELECT e.eventid, COUNT(b.customer_customerid) AS attendance
FROM event e LEFT JOIN booking b
ON e.eventid = b.event_eventid
GROUP BY e.eventid
)
) WHERE attendance < avg_attendance;
The above will give you a list of eventids - you can get the rest of the columns you need by querying the event table with this list.
Edited based on comments - poster would like to determine the events for each concert with below average attendance for that concert.
SELECT concertid, eventid, attendance, avg_attendance FROM (
SELECT concertid, eventid, attendance, AVG(attendance) OVER ( PARTITION BY concertid ) AS avg_attendance
FROM (
SELECT c.concertid, e.eventid, COUNT(b.timeofarrival) AS attendance
FROM concert c INNER JOIN event e
ON c.concertid = e.concert_concertid
LEFT JOIN booking b
ON e.eventid = b.event_eventid
GROUP BY e.eventid
)
) WHERE attendance < avg_attendance;

Related

How do I create a time frame window for customer purchases from a database where each row is a unique purchase?

I have a table in BigQuery, where each row represents a unique purchase made by a customer. The table has customer ID, what they purchased, when it was purchased and how many times we have seen that customer.
I want to create a table that contains a row of the customers first purchase and anything they bought within 31 days of this purchase.
I also want a new row for their second purchase and again, anything they bought within 31 days of this purchase.
Im trying to see if there are any patterns here, to help drive CRM campaigns.
If this would be easier in python, I can use that also.
I tried using something like this:
SELECT t1.ID, t1.ITEM as FIRST_PURCHASE, t2.ITEM as SECOND_PURCHASE, t3.ITEM as THIRD_PURCHASE
FROM `TABLE` as t1
left join `TABLE` as t2
on t1.ID = t2.ID and t1.PURCHASE_NUMBER = t2.PURCHASE_NUMBER+1
left join `TABLE` as t3
on t1.ID = t2.ID and t1.PURCHASE_NUMBER = t3.PURCHASE_NUMBER+2
where (t2.DATE_DIFF <= 31) and (t3.DATE_DIFF <= 31)
But obviously I only get a 31 day window from the first purchase, and no 31 day windows from any future purhases. I also thought I might be able to attempt this in python using pivot?
I think you can approach it somewhat like this:
with purchases as (
-- dummy column names
select customerID, item, date, visits from `project.dataset.table`
),
purchase_ordering as (
select *, row_number() over (partition by customerID order by date asc) as rn
from purchases
),
first_two_purchases as (
select
* except(rn),
case when rn = 1 then 'First Purchase' else 'Second Purchase' end as purchase_order
from purchase_ordering
where rn <= 2
),
additional_purchase_logic as (
select
ftp.purchase_order,
ftp.customerID,
ftp.item,
ftp.date,
array_agg(struct(p.item,p.date)) as within_31_days_of_purchase
from first_two_purchases ftp
left join purchases p using(customer_id)
where p.date > ftp.date and p.date <= date_add(ftp.date, interval 31 day)
group by 1,2,3,4
)
select * from additional_purchase_logic
Note, if your 2nd purchases is within 31 days of first purchase, it will show up as a subsequent purchase in your 'First Purchase' row as well as an independent record in your 'Second Purchase' row.

sqlite combine 2 queries from different tables to make one

I recently took to using sql again, the last time I used it was in microsoft access 2000 so please bear with me if I'm behind the times a little.
I have 2 pointless virtual currencies on my discord server for my players to play pointless games with. Both of these currencies' transactions are currently stored in individual tables.
I wish to sum up all the transactions for each player to give them a single current amount for each currency. Individually I can do this:
SELECT
tblPlayers.PlayerID AS PlayerID,
tblPlayers.Name AS Name,
SUM(tblGorillaTears.Amount)
FROM
tblPlayers
INNER JOIN
tblGorillaTears
ON
tblPlayers.PlayerID = tblGorillaTears.PlayerID
GROUP BY
tblPlayers.PlayerID;
and
SELECT
tblPlayers.PlayerID AS PlayerID,
tblPlayers.Name AS Name,
SUM(tblKebabs.Amount)
FROM
tblPlayers
INNER JOIN
tblKebabs
ON
tblPlayers.PlayerID = tblKebabs.PlayerID
GROUP BY
tblPlayers.PlayerID;
What i need is a table that outputs the user name the id and the total for each currency on one row, but when i do this:
SELECT
tblPlayers.PlayerID AS PlayerID,
tblPlayers.Name AS Name,
SUM(tblGorillaTears.Amount) AS GT,
0 as Kebabs
FROM
tblPlayers
INNER JOIN
tblGorillaTears
ON
tblPlayers.PlayerID = tblGorillaTears.PlayerID
GROUP BY
tblPlayers.PlayerID
UNION
SELECT
tblPlayers.PlayerID AS PlayerID,
tblPlayers.Name AS Name,
0 as GP,
SUM(tblKebabs.Amount)
FROM
tblPlayers
INNER JOIN
tblKebabs
ON
tblPlayers.PlayerID = tblKebabs.PlayerID
GROUP BY
tblPlayers.PlayerID;
the results end in a row for each player for each currency. How can i make it so both currencies appear in the same row?
Previously in MSAccess i was able to create two queries and then make a query of those two queries as if they were a table, but I cannot figure out how to do that in this instance. Thanks <3
UNION will add new rows for sure, you can try like following query.
SELECT TP.playerid AS PlayerID,
TP.NAME AS NAME,
(SELECT Sum(TG.amount)
FROM tblgorillatears TG
WHERE TG.playerid = TP.playerid) AS GT,
(SELECT Sum(TG.amount)
FROM tblkebabs TG
WHERE TG.playerid = TP.playerid) AS Kebabs
FROM tblplayers TP

Select one column (with multiple rows) 5 times from the same table with different dates in the where clause

The DB records all user activity daily. I am trying to compile a summary report to display total number of actions per day per user. The problem is I want to stack the results next to each other. I have refered to the following stackoverflow questions.
mysql Select one column twice from the same table with different dates in the where clause
Select two columns from same table with different WHERE conditions
but I still continue to get the "subquery returns more than one row error #1242". All help is appreciated. Thank you.
This is my query, just for 2 days to start with.
SELECT LOGGEDIN_USER AS EnquiryHero,
( SELECT COUNT(user_id) from applications
DATE_TIME like "2016-08-24%" group by user_id ) as Day1,
( SELECT COUNT(user_id)from applications
WHERE DATE_TIME like "2016-08-25%" group by user_id ) as Day2,
from applications WHERE DATE_TIME like "2016-08-24%" group by user_id;
--
SELECT user_id,
( SUM( IF( the_day ='2016-08-24', ct, 0 ))) AS 2016-08-24,
( SUM( IF( the_day ='2016-08-25', ct, 0 ))) AS 2016-08-25,
( SUM( IF( the_day ='2016-08-26', ct, 0 ))) AS 2016-08-26,
( SUM( IF( the_day ='2016-08-27', ct, 0 ))) AS 2016-08-27,
FROM ( select user_id, DATE(date_time) AS the_day, loggedin_user, COUNT(*) AS ct
FROM applications GROUP BY 1,2 ) AS x
GROUP BY user_id;
First focus on getting the data; then focus on "pivoting" the data.
SELECT user_id,
DATE(`date_time`) AS the_day,
COUNT(*) AS ct
FROM applications
GROUP BY 1, 2;
See if that gives you the data desired; then look at how to "pivot". See the extra tag I added.
Then pivot
SELECT user_id,
(SUM(IF(the_day = '2016-08-24', ct, 0) AS '2016-08-24',
(SUM(IF(the_day = '2016-08-25', ct, 0) AS '2016-08-25',
(SUM(IF(the_day = '2016-08-26', ct, 0) AS '2016-08-26',
(SUM(IF(the_day = '2016-08-27', ct, 0) AS '2016-08-27',
...
FROM (
the query above
) AS x
GROUP BY user_id;

Nested Sum( ) query is not working in mysql

i'm having a problem in calculating total bill of a ptient. I have three tables named as "test", "pharmacy", "check".
Columns in test are:
patient_ID
testname
rate
Columns in pharmacy are:
patient_ID
medicineDescription
qty
rate
Columns in check are:
patient_ID
doctorID
fees
date
I have a table Bill that will store total amount of a patient.
patient_ID
amount
date
I have used the following query. But it's giving the following error.
$result = mysqli_query($data, "SELECT patient_ID, (SUM(pharmacy.qty*pharmacy.rate ) + SUM(test.rate) + SUM(check.fees))
AS total FROM pharmacy, test, check WHERE patient_ID= '$pID'" );
Correct query should be, closing bracket was missing at the end of subquery (... AS total FROM pharmacy**)**):
$result = mysqli_query ($data, "SELECT patient_ID,
(SUM(pharmacy.qty*pharmacy.rate ) + SUM(test.rate) + SUM(check.fees)) AS total FROM pharmacy),
test,
check
WHERE patient_ID= '$pID'" );
You have three tables in your from clause, but with no join condition - this means you're pairing each row with all the other rows, which is obviously not what you intended. One way to handle this is to use proper joins:
SELECT p.patient_id, pharmacy_sum + test_sum + fees_sum AS total
FROM (SELECT patient_id, SUM(qty * rate) AS pharmacy_sum
FROM pharmacy
WHERE patient_ID= '$pID'
GROUP BY patient_id) p
JOIN (SELECT patient_id, SUM(rate) AS test_sum
FROM test
WHERE patient_ID= '$pID'
GROUP BY patient_id) t ON p.patient_id_id = t.patient_id
JOIN (SELECT patient_id, SUM(fees) AS fees_sum
FROM check
WHERE patient_ID= '$pID'
GROUP BY patient_id) c ON p.patient_id_id = c.patient_id

Give the employee(fname and lname) that make the most money in each dept

SELECT max(salary), dept
FROM Employees
GROUP BY dept;
How to add fname and lname without the errors? If I add them in group by, I no longer get the max salary.
This is how I would do it in SQL Server... You need a subquery that returns the max salary for each department, then join that back to the employee table to figure out which employee has that salary for that department:
SELECT D.Dept, D.MaxSalary, Employees.FName, Employees.LName
FROM (
SELECT MAX(Salary) AS MaxSalary, Dept
FROM Employees
GROUP BY dept
) D
INNER JOIN Employees
ON Employees.Dept = D.Dept
AND Employees.Salary = D.MaxSalary

Resources