JOIN & List Last Records per an ID - mysql

There are two tables:
SELECT id,customer FROM records;
SELECT user_id,call_date FROM call_history
Matching columns are:
records.id = call_history.user_id
The call_history table has call logs for customers.
There can be one or more call_history rows per customer.
I need to find when they called last time (for each customer).
For ex. userid=1 called twice, June 16 and July 20. Result must give me July 20, but I need to do the same for all customers from records table.
That is what I tried but it didn't work:
SELECT a.id, FROM_UNIXTIME(b.call_date,'%d/%m/%Y %H:%i') AS lastcall
FROM records a
INNER JOIN call_history b ON a.id=b.user_id
GROUP BY a.id ORDER BY b.call_date DESC;
Thank you.

Does this meet your requirements?
SELECT
r.id,
r.customer,
MAX(ch.call_date) AS lastcall
FROM
records AS r
INNER JOIN
call_history AS ch ON ch.user_id = r.id
GROUP BY
r.id,
r.customer

Related

Inner Join for 3 tables with SUM of two columns in SQL Query?

I have the following three tables:
I have Following Query to Join Above 3 Tables
customer.customer_id,
customer.name,
SUM(sales.total),
sales.created_at,
SUM(sales_payments.amount)
FROM
sales INNER JOIN customer ON customer.customer_id = sales.customer_id
INNER JOIN sales_payments ON sales.customer_id = sales_payments.customer_id
WHERE sales.created_at ='2020-04-03'
GROUP By customer.name
Result for Above Query is given below
Sum of sales.total is double of the actual sum of sales.total column which has 2-row count, I need to have the actual SUM of that column, without doubling the SUM of those rows, Thank you, for your help in advance..
PROBLEM
The problem here is that there are consecutive inner joins and the number of rows getting fetched in the second inner join is not restricted. So, as we have not added a condition on sales_payment_id in the join between the sales and sales_payment tables, one row in sales table(for customer_id 2, in this case) would be mapped to 2 rows in the payment table. This causes the same values to be reconsidered.
In other words, the mapping for customer_id 2 between the 3 tables is 1:1:2 rather than 1:1:1.
SOLUTION
Solution 1 : As mentioned by Gordon, you could first aggregate the amount values of the sales_payments table and then aggregate the values in sales table.
Solution 2 : Alternatively (IMHO a better approach), you could add a foreign key between sales and sales_payment tables. For example, the sales_payment_id column of sales_payment table can be introduced in the sales table as well. This would facilitate the join between these tables and reduce additional overheads while querying data.
The query would then look like:
`SELECT c.customer_id,
c.name,
SUM(s.total),
s.created_at,
SUM(sp.amount)
FROM customer c
INNER JOIN sales s
ON c.customer_id = s.customer_id
INNER JOIN sales_payments sp
ON c.customer_id = sp.customer_id
AND s.sales_payments_id = sp.sales_payments_id
WHERE s.created_at ='2020-04-03'
GROUP BY c.customer_id,
c.name,
s.created_at ;`
Hope that helps!
You have multiple rows for sales_payments and sales per customer. You need to pre-aggregate to get the right value:
SELECT c.customer_id, c.name, s.created_at, s.total, sp.amount
FROM customer c JOIN
(SELECT s.customer_id, s.created_at, SUM(s.total) as total
FROM sales s
WHERE s.created_at ='2020-04-03'
GROUP BY s.customer_id, s.created_at
) s
ON c.customer_id = s.customer_id JOIN
(SELECT sp.customer_id, SUM(sp.amount) as amount
FROM sales_payments sp
GROUP BY sp.customer_id
) sp
ON s.customer_id = sp.customer_id

SQL Query for getting maximum value from a column Joining from Another Table

This is a slight variant of the question I asked here
SQL Query for getting maximum value from a column
I have a Person Table and an Activity Table with the following data
-- PERSON-----
------ACTIVITY------------
I have got this data in the database about users spending time on a particular activity.
I intend to get the data when every user has spent the maximum number of hours.
My Query is
Select p.Id as 'PersonId',
p.Name as 'Name',
act.HoursSpent as 'Hours Spent',
act.Date as 'Date'
From Person p
Left JOIN (Select MAX(HoursSpent), Date from Activity
Group By HoursSpent, Date) act
on act.personId = p.Id
but it is giving me all the rows for Person and not with the Maximum Numbers of Hours Spent.
This should be my result.
You have several issues with your query:
The subquery to get hours is aggregated by date, not person.
You don't have a way to bring in other columns from activity.
You can take this approach -- joins and group by, but it requires two joins:
select p.*, a.* -- the columns you want
from Person p left join
activity a
on a.personId = p.id left join
(select personid, max(HoursSpent) as max_hoursspent
from activity a
group by personid
) ma
on ma.personId = a.personId and
ma.max_hoursspent = a.hoursspent;
Note that this can return duplicates for a given person -- if there are ties for the maximum.
This is written more colloquially using row_number():
select p.*, a.* -- the columns you want
from Person p left join
(select a.*,
row_number() over (partition by a.personid order by a.hoursspent desc) as seqnum
from activity a
) a
on a.personId = p.id and a.seqnum = 1
ma.max_hoursspent = a.hoursspent;

Min Max dates as new columns in sql

I have two tables with several columns. All I want is to join both the tables and create two more columns of min and max dates. For example
table data [columns]
ID date instrument
table people
ID birth country
All I want is join these two tables and add two more columns in the "people" table with min and max date groupby ID, as single ID contains a number of dates in data table.
You may try below query -
SELECT P.ID, P.birth, P.country, MIN(D.date) MIN_DATE, MAX(D.date) MAX_DATE
FROM DATA D JOIN PEOPLE P ON D.ID = P.ID
GROUP BY P.ID, P.birth, P.country
SELECT SUB_QUERY.*,MIN(D.DATE) FROM
(SELECT * FROM PEOPLE AS P LEFT JOIN ON DATA AS D) AS SUB_QUERY
GROUP BY P.ID
ORDER BY D.DATE ASC

Sql query to add missing rows from another table

I have a table A (columns: id, year,month,amount) and table B( columns: id, year,month, amount=0).
Table A is the master table which have a same set of ids for each month for every year from 2011 to 2016.
In that some records are not present (like their is no record for 123456 id for 03 month and 2016 year and 468976 amountk), for that I want to add new record having id 123456, 03 in month and 2016 in year in table A and as it is a missing record amount will be 0.
The missing records are taken from table B which is having same set of ids from table A and for each id it is having every month for every year from 2011 to 2016, for each row amounts as 0.
Note:
1. In table A record s are not sorted and in table records are grouped by id, year and month.
2. If possible please make it normal sql queries instead of pl/sql. If not possible as I wanted please suggest your answer.
Thanks in advance........I hope you understsnd the problem statement.
You can generate the records using a cross join and some more logic:
select i.id, ym.year, ym.month
from (select distinct year, month from a) ym cross join
(select distinct id from b) i left join
a
on a.year = ym.year and a.month = ym.month and b.id = i.id
where a.id is null;
(I think I have the as and bs right. I'm not sure why two separate tables are mentioned in the question. It would seem that a is missing the records, so it is the only table needed. My best guess is that b is a subset of ids in a.)
Here is a version that does the insert:
insert into a(id, year, month)
select i.id, ym.year, ym.month
from (select distinct year, month from b) ym cross join
(select distinct id from b) i left join
b
on b.year = ym.year and b.month = ym.month and b.id = i.id
where b.id is null;

How to count all row result as 1 in mysql?

I have two tables. "tbl_a" which contain fields of patient and hospital, and "tbl_b" which is the consultation.
Now my problem is to only count the patient that has 4 records in "tbl_b" so that if a patient has 4 records in the "tbl_b" then it count as 1.
I want this result only in use of mysql coz and i need this to run in event scheduler.
In short i want to count all patient that has 4 consultation in every hospital. Can anybody help me on this?
Use this solution:
SELECT patient
FROM tbl_b
GROUP BY patient
HAVING COUNT(1) >= 4
Change the >= to = if you just want patients who have exactly four consultations instead of four or more.
Perhaps you want the count of patients who have four or more consultations... in which case you could just wrap the above SELECT and count the number of rows:
SELECT COUNT(1)
FROM
(
SELECT patient
FROM tbl_b
GROUP BY patient
HAVING COUNT(1) >= 4
) a
Assuming tables patients and consultation Joined by patient_id
SELECT * FROM patients
JOIN (SELECT IF(COUNT(patient_id) = 4, patient_id, NULL) AS con
FROM consultation
GROUP BY patient_id) AS con
ON con.patient_id = patients.patient_id
GROUP BY patient_id
the joined table would get only numbers fro consultations which are 4 and all others are NULL hence the join clause in the case would result in records of patients having consultations total 4 only
hope this helps
Try this ::
Select *, count(1)
from table_a a
inner join table_b b
inner join on (a.patient_id=b.patient_id)
group by b.patient_id having count(1) =4
Try this
SELECT
COUNT(consultation )/4 AS Patient_Number
FROM
tbl_b
GROUP BY
consultation
HAVING
(COUNT(consultation ) % 4) = 0