missing data in mysql table - mysql

please help me to write this query.I have tried with leftjoin but its not working.
I have two table tdate and tollname. In tdate table I have dates only, like say of one month and second table tollname I have names of toll with dates.
I want to find toll wise dates missing from table tollname.
Table name: tdate
Dates
1
2
3
4
...
30
Tollname
Dates TollName
1 A
1 B
1 C
5 A
5 B
6 C
9 B
12 A
12 B
12 C
28 A
28 B
30 C

You can just use a cross join and left join (or equivalently not exists/not in). This generates all the combinations of the tollname and date, and then returns the ones that are not present in your table:
select d.date, t.tollname
from tdate d cross join
(select distinct tollname from tollname) t
where not exists (select 1
from tollname t2
where d.date = t2.date and t.tollname = t2.tollname
);
If you have a separate table with the tollnames, then you can use that instead of the subquery:

SQL FIDDLE DEMO
SELECT D.*
FROM tdate D
LEFT JOIN Tollname T
ON D.Dates = T.Dates
WHERE T.Dates IS NULL

SELECT d.* from tdate d left join Tollname t on d.Dates = t.Dates
WHERE t.TollName is null

Related

How to join tables with aggregate functions in MYSQL query?

I have two tables from the database and I want to get the last status of each id. Tried adding the INNER JOIN claus but no avail. These are what my data looks like:
Table: employee
id name department
-------------------------
1 A X
2 B Y
3 C Z
Table: timelog
id time status count
-------------------------------
1 08:51 IN 1
3 09:00 OUT 2
2 09:00 IN 3
2 18:00 OUT 4
1 18:05 OUT 5
Currently, this is the query that I use but need to get the name of each employee.
SELECT
*
FROM timelog
WHERE timelog.count
IN (SELECT MAX(timelog.count)
FROM timelog
GROUP BY timelog.id)
ORDER BY clock.id;
Current output:
id time status
-------------------------------
1 18:05 OUT
2 18:00 OUT
3 09:00 OUT
This is the output I want to achieve:
id name time status
-------------------------------
1 A 18:05 OUT
2 B 18:00 OUT
3 C 09:00 OUT
Is it possible to add JOIN to the above query? If no, what would be the workaround? Any help would be greatly appreciated. TIA.
Use a correlated subquery to get the last record for each id in timelog:
SELECT e.*, tl.*
FROM employee e JOIN
timelog tl
ON e.id = tl.id
WHERE tl.count = (SELECT MAX(tl2.count)
FROM timelog tl2
WHERE tl2.id = tl.id
) ;
Note that your version of the query is not correct. The subquery returns the maximum count for each id. However, the outer query might match a different id to the count in the subquery. The correlation clause fixes this problem.
You can join the tables and use a correlated subquery for filtering:
select
e.id,
e.name,
t.time,
t.status
from employee e
inner join timelog t on t.id = e.id
where t.count = (
select max(count)
from timelog t1
where t1.id = t.id
)

Group by with latest record on join query

Here is my table deals_transaction_status_log with the following fields
id,user_id,deal_transaction_id,transaction_status_id in which i want to fetch the records with group by on transaction_id with latest record on(max id).
This table also join some another tables to get some other data.
Here is my query
SELECT dtsl.id ,dtsl.deal_transaction_id,dts.id as statusId
FROM deals_transaction_status_log as dtsl
JOIN deals_transactions as dt ON dt.id=dtsl.deal_transaction_id AND dt.visitor_id=140
JOIN DEALS as d ON d.idDeal=dt.deal_id
JOIN USER as u ON d.userId=u.idUser
JOIN deals_transaction_status as dts ON dts.id=dtsl.transaction_status_id
WHERE dtsl.user_id!=140 AND dtsl.transaction_status_id=14 AND dtsl.id IN (
SELECT MAX(dtsl.id)
FROM deals_transaction_status_log as dtsl
GROUP BY dtsl.deal_transaction_id
) GROUP BY dtsl.deal_transaction_id
This works fine however it returns only one record even if i have more than one record with same deal_transaction_id
for eg:
Sample Input
id user_id deal_transaction_id transaction_status_id
1 4 2 14
2 4 2 14
3 5 3 14
4 5 3 14
Result
id statusId deal_transaction_id
3 14 3
Expected result
id statusId deal_transaction_id
2 14 2
4 14 3
UPDATE
I just tried fa06 answer without any join
SELECT dtsl.id,dtsl.deal_transaction_id,dtsl.transaction_status_id FROM deals_transaction_status_log as dtsl
WHERE dtsl.id IN (
SELECT MAX(id)
FROM deals_transaction_status_log as b where dtsl.transaction_status_id=b.transaction_status_id)
AND dtsl.transaction_status_id=14
GROUP BY dtsl.deal_transaction_id
But still i am getting only one row
use correlated subquery
SELECT dtsl.id ,dtsl.deal_transaction_id,dts.id as statusId
FROM deals_transaction_status_log as dtsl
JOIN deals_transactions as dt ON dt.id=dtsl.deal_transaction_id AND dt.visitor_id=140
JOIN DEALS as d ON d.idDeal=dt.deal_id
JOIN USER as u ON d.userId=u.idUser
JOIN deals_transaction_status as dts ON dts.id=dtsl.transaction_status_id
WHERE dtsl.user_id!=140 AND dtsl.transaction_status_id=14 AND dtsl.id IN (
SELECT MAX(id)
FROM deals_transaction_status_log as b where dtsl.deal_transaction_id=b.deal_transaction_id)

Select date closest to date in another table

I have two tables, one having a entry date, and the other with an effective date. What I need to do is select the row were the entrydate is closest to the effective date. The only resource I can find is row_number() which does not seem to work in MySQL.
data
Table A Table B
id effdate id Aid entrydate
1 2015-10-19 1 1 2015-12-17
2 1 2015-12-18
3 1 2015-12-20
What I am trying to do is select
id effdate entrydate
1 2015-10-19 2015-12-17
So far I have tried using min() on entrydate, but it will just time out.
SELECT a.id, a.effdate, b.entrydate
FROM tableA a
JOIN tableB b on a.id = b.Aid
SELECT a.id, a.effdate, b.entrydate
FROM tableA a
JOIN tableB b on a.id = b.Aid
ORDER BY DATEDIFF(entrydate, effdate) ASC
-- you might want to order here by additional fields to break the ties
LIMIT 1;
If entry date is always greater than the effective date you can use the following
select a.id, a.effdate, b.entrydate from aa a, bb b
where a.id = b.aid
and b.entrydate = (select Min(bi.entrydate)
from bb bi
where bi.id = a.id
);

Query to find elements in particular time interval

I need to find a Hive query that returns the 2 top names for each 6 minutes interval since 00:00:00,
Data looks like -
Name Time
A 00:00:00
B 00:03:53
C 00:01:16
A 00:04:34
A 00:07:32
A 00:18:36
C 00:16:12
C 00:05:04
B 00:01:50
B 00:12:05
A 00:11:20
B 00:04:27
B 00:02:47
A 00:00:23
A 00:00:23
B 00:36:21
B 00:02:46
I would like to write the query in Hive which is very new for me but even using mysql query , I can derive the result in Hive.
select
*
from
(
select NAME
, time_interval_6
, rank() over (partition by NAME, time_interval_6 order by ct desc) as ranking
from
(select count(1) as ct
, NAME
, floor((floor(cast(substring(time,1,2) as int)*60 + cast(substring(time,4,2) as int)))/6) as time_interval_6
FROM MY_TABLE
group by NAME, floor((floor(cast(substring(time,1,2) as int)*60 + cast(substring(time,4,2) as int)))/6)
) a
)b
where ranking <= 2
;

Mysql refrencing derived tables from nested query

I posted something similar to this yesterday, but now I'd like something a little different from my query-
I'm trying to query a database to retrieve the number of one-time users who have visited a website over time. The data looks something like this:
Day | UserID
1 | A
1 | B
2 | B
3 | A
4 | B
4 | C
5 | D
I'd like the query result to look this this
Time Span | COUNT(DISTINCT UserID)
Day 1 to Day 1 | 2
Day 1 to Day 2 | 1
Day 1 to Day 3 | 0
Day 1 to Day 4 | 1
Day 1 to Day 5 | 2
The result is 2,1,0,1,2 because, at the end of those days, there are X number of users who have visited a single time. e.g. for day 5, at the end of day 5, users c and d have visited only once each.
I think I'm looking for a query similar to this:
select d.day, (select count(distinct userid) from visits where day<=d.day)
from (select distinct day from visits) d
The difference between the query above and what I'm looking for is that I'd like this new query to consider only one-time users for each time span, and not repeat users.
Thanks
This subquery should work for the clarified requirements.
select d.day, count(distinct case when b.userid is null then a.userid end)
from (select day from visits group by day) d
inner join
(
select a.day, a.userid, count(*) c
from visits a
join visits b on a.userid=b.userid and b.day <= a.day
group by a.day, a.userid
having count(*) = 1
) a on a.day <= d.day
left join
(
select a.day, a.userid, count(*) c
from visits a
join visits b on a.userid=b.userid and b.day <= a.day
group by a.day, a.userid
having count(*) > 1
) b on a.userid = b.userid and b.day <= d.day
group by d.day
Original
You must have taken the idea from SQL Server - it is the only RDBMS (IIRC) that will allow you to reference a twice removed (nesting) query. Please indicate what you want and we can rewrite the query.
For the exact query shown, you don't need 2 levels of subquery
SELECT
C.col_c1 AS Data,
(
SELECT count(col_b1)
FROM tbl
WHERE col_b2 <= C.col_c1
) A
FROM (
SELECT col_c1 # subquery to get distinct c1
FROM tbl
GROUP BY col_c1) C;