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
);
Related
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
)
Assuming I have this table
tableA
ID value
1 5
1 5
3 10
2 4
2 2
1 2
tableB
ID Name
1 apple
2 carrot
3 banana
If the expected max value of apple is 10, carrot is 5, and banana is 15 the output table would be
table output
ID Name value
1 apple 12
2 carrot 6
what SQL statement I need to solve this?
what I have done so far:
SELECT a,ID, b.name , sum(a.valueSUM) AS value FROM tableA a
INNER JOIN tableB b
ON a.id = b.id
GROUP BY id
what options i need on the WHERE clause to pull this off?
The inner subquery groups them normally and then the main query is what deals with limiting the results.
SELECT * FROM
(select
b.id,
b.name as name,
SUM(a.value) as the_sum
from tableA a inner join tableB b
on a.Id = b.id
group by b.name, b.id
) y
where (name = 'apple' and the_sum >= 10) OR
(name = 'banana' and the_sum >= 15) OR
(name = 'carrot' and the_sum >= 5)
It seems your sample data has changed, please try this. I thought the ID doesnt have to follow tableA/tableB's id and the id is auto-generated as per the results.
Would be nice if you have another table that sets the threshold per name
Assuming threshold can be specified in tableB (makes sense):
SELECT a.ID, b.name, sum(a.value) AS value
FROM tableA a
INNER JOIN tableB b
ON a.id = b.id
GROUP BY a.ID, b.name, b.Threshold
HAVING sum(a.value) > b.Threshold;
Demo: http://rextester.com/ICOQF10295
SELECT TableB.id, TableB.Name, MAX(TableA.value) AS Value
FROM TableA INNER JOIN TableB ON
TableA.id = TableB.id
GROUP BY TableB.id, TableB.Name
Instead of SUM, use MAX aggregate function
This works in SQL Server
--Existing tables
create table #tableA (ID int, value int)
create table #tableB (ID int, Name varchar(30))
insert into #tableA
select 1 , 5 union all
select 1 , 5 union all
select 3 , 10 union all
select 2 , 4 union all
select 2 , 2 union all
select 1 , 2
insert into #tableB
select 1 , 'apple' union all
select 2 , 'carrot' union all
select 3 , 'banana'
--Create new temporary table #tableC
create table #tableC (ID int, MAXvalue int)
insert into #tableC
select 1 , 10 union all
select 2 , 5 union all
select 3 , 15
select c.ID,b.Name, a.value from #tableC c
inner join #tableB b on b.ID = c.ID
inner join (
select ID,SUM(value) as value from #tableA
group by ID
) a on a.ID = c.ID
where a.value >= c.MAXvalue
drop table #tableA
drop table #tableB
drop table #tableC
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
I have the following 2 tables:
create table1
(
SENDER int,
RECEIVER int,
TIME time,
TYPE char(1)
);
create table2
(
ID int,
Y int,
CONTACT int,
DATE time
);
I am executing the following join query:
SELECT B.ID, A.RECEIVER AS Z, A.SENDER AS CONTACT, A.TYPE, A.TIME
FROM table1 A
JOIN table2 B ON A.RECEIVER = B.CONTACT
WHERE A.TYPE = 'A'
AND A.TIME < B.DATE
How do I modify the query to return only the top 40 results for each (ID,CONTACT) pair using GROUP BY?
I can order the data using the field table2.DATE
since i wanted top 40 results for each ID, i made ID,autoId as a primary key, here autoId is an autoincrement key. so after executing the following query:
SELECT B.ID, A.RECEIVER AS Z, A.SENDER AS CONTACT, A.TYPE, A.TIME
FROM table1 A
JOIN table2 B ON A.RECEIVER = B.CONTACT
WHERE A.TYPE = 'A'
AND A.TIME < B.DATE
i get results such that, the autoId initializes to 1 for each ID
for eg:
ID CONTACT autoId
1 2 1
1 3 2
1 11 3
1 34 4
2 5 1
2 33 2
2 56 3
since autoId is autoincrement, there is already an index on it. after this table is created, i can easily delete the results where autoId is greater than 40. and this while process runs really fast!
a table
a_id a_value
1 text1
2 test2
b table
b_id b_num a_id
1 5 1
2 7 1
3 2 1
4 7 2
5 56 2
Results base a table (edited)
a_id:1 a_value:text1 total:3 records
a_id:2 a_value:text2 total:2 records
How can get this format in sql?
query a table and add a field(total) count b.a_id = a.a_id in table b
thank you..
You can try:
SELECT a.a_id AS id, a.a_value AS value, (SELECT count(b.b_id) AS count FROM b WHERE (b.a_id = a.a_id)) AS total FROM a GROUP BY a.a_id
Then the result for your example using the data from tables a and b:
**id value total**
1 text1 3
2 text2 2
I imagine you have an error in your b table, so I will assume what you call b_id is actually a_id, or your results would be wrong
Anyway you could use:
SELECT COUNT(b.a_id) AS total FROM b GROUP BY (SELECT a.a_id FROM a)
ORDER BY b.a_id
The updated query based on changes to the question
SELECT a_id, a_value, x.total
FROM a
INNER JOIN
(SELECT b.a_id, COUNT(1) AS total
FROM b
GROUP BY (b.a_id)) X
ON a.a_id = x.a_id
ORDER BY a.a_id