Get results based on conditions in other table - sql

I have a table
Orders
ID User
-----------------
1 Matt
2 Chris
3 John
then I have another table
Order_Contact
ID Order_ID Type Timestamp
-------------------------------------------------------------------
1 1 Request 2018-01-01 10:00:00
2 1 Request 2018-01-01 10:35:00
3 1 Response 2018-01-01 11:00:00
4 1 Request 2018-01-01 12:00:00
5 2 Request 2018-01-01 13:00:00
6 2 Response 2018-01-01 14:00:00
My goal is to create a query that returns all Orders that have "open" contact requests that have no response. One response is enough to satisfy multiple requests. Requests that have no response at later datetime than the request are "open". How could I achieve this?
In the above scenario I would like to return
ID User
----------------
1 Matt

First, get the latest entry per order:
SELECT Type, MAX(ID)
FROM Order_Contact
GROUP BY Order_ID
Then, filter the "open" entries:
SELECT *
FROM (
SELECT Type, MAX(ID)
FROM Order_Contact
GROUP BY Order_ID
) as max_id
WHERE max_id.Type = 'Request'
Edit:
The solution above works for my MySQL-Installation, but the following solution works even using sqlfiddle (http://sqlfiddle.com/#!9/92ecd4/12):
SELECT *
FROM (
SELECT *
FROM Order_Contact
WHERE ID IN (
SELECT MAX(ID)
FROM Order_Contact
GROUP BY Order_ID
)
) as Reduced_Order_Contact
WHERE Reduced_Order_Contact.Type = 'Request'
Edit 2:
Towards the extension of the question, adding columns is a simple join:
SELECT Orders.ID, Orders.User
FROM (
SELECT *
FROM Order_Contact
WHERE ID IN (
SELECT MAX(ID)
FROM Order_Contact
GROUP BY Order_ID
)
) as Reduced_Order_Contact
INNER JOIN Orders
ON Reduced_Order_Contact.Order_ID = Orders.ID
WHERE Reduced_Order_Contact.Type = 'Request'

Check this query
select
Orders.ID, Orders.[User]
from (
select
*, max([Timestamp]) over (partition by Order_ID) maxDate
from
Order_Contact
) t
join Orders on t.Order_ID = Orders.ID
where
t.maxDate = t.[Timestamp]
and t.[Type] = 'Request'
Updated query due to changes in the question

Related

How do I get the count for orders with a certain code only when there are multiple codes for the same order possible

Sorry this is my first post - please let me know if something doesn't make sense!
I'm trying to get a count of the number of orders with a specific code XXX ONLY
lets say table A looks something like this
|ORDER ID | ITEM CODE |
123 XXX
123 YYY
123 YYY
456 XXX
456 XXX
456 XXX
789 XXX
000 YYY
what i want in the output is:
order 123 and 000 not to count
and order 456 and 789 to count as 1 each
I only want the count of the unique orders which have item code XXX ONLY
so the count/ output of the final query should be 2
currently what i have is
select order_id, item code, count(order_id) from table a
where item code = 'XXX'
group by order_id, item code
order by count(order_id)
which outputs me the following
ORDER_ID | ITEM CODE | COUNT(ORDER_ID)
123 XXX 1
345 XXX 3
789 XXX 1
This is wrong because I want the output as described above
Thanks in advance!
select order_id
from table_a
group by order_id
having min(item_code) = 'XXX'
and max(item_code) = 'XXX'
Seems like you want this :
select distinct order_id , item_code , 1 as count
from table t1
where not exists (
select 1 from table t2
where t1.order_id = t2.order_id
and t2.item_code <> 'XXX'
)
the count would be always 1 per your question
One option is to use an anti-join. For example:
select distinct t.order_id, 1 as cnt
from table_a t
left join table_a u on u.order_id = t.order_id and u.item_code <> 'XXX'
where t.item_code = 'XXX' and u.order_id is null
Result:
ORDER_ID CNT
--------- ---
789 1
456 1
See running example at db<>fiddle.
EDIT
To get the total count only, tweak the query as shown below:
select count(distinct t.order_id) as cnt
from table_a t
left join table_a u on u.order_id = t.order_id and u.item_code <> 'XXX'
where t.item_code = 'XXX' and u.order_id is null
Result:
CNT
---
2
See running example at db<>fiddle.

Select SQL query that fill the missing value from another select

I have the table user1 :
id |date
1 2018-01-01
2 null
3 2018-01-01
4 null
and another table user2:
id |date_buy
1 2018-01-01
1 2018-01-02
2 2018-01-01
2 2018-01-02
3 2018-01-01
4 2018-01-01
I would like to make a select query that select the id and the date from the table user1 but if the date field is null then it shall take the minimal date_buy for this user and fill the missing with it.
So my first idea was:
- make a simple query on the first table
SELECT id, date from user1
make a simple query on the second table
SELECT id, min(date_buy) as date from user2 group by id
union the two query and make a distinct where date is not null
Which give something like :
SELECT distinct id, date
from (SELECT id, date
from user1
UNION
select id, min(date_buy) as date
from user2 group by id)
where date is not null
But I struggle to shape this and make it work.
In Hive, I think I would do:
select u1.id, coalesce(u1.date, u2.min_date)
from user1 u1 left join
(select id, min(date_buy) as min_date
from user2
group by id
) u2
on u1.id = u2.id;
this should work
select u1.id,COALESCE(u1.date, u2.min_dt) from user1 as u1
join
( select id,MIN(date_buy) as min_dt from user2 group by id
) as u2
on u1.id=u2.id;

find all rows after the recent update using oracle

I tried below query to bring all rows after last Action="UNLOCKED", but ORDER BY is not allowed in subquery it seems.
SELECT *
FROM TABLE
WHERE id >= (SELECT MAX(id)
FROM TABLE
WHERE ACTION='UNLOCKED' AND action_id=123
ORDER BY CREATE_DATE DESC);
Sample data
Id action_id Action ... CREATE_DATE
1 123 ADD 03/18/2018
2 123 Unlocked 03/19/2018
3 123 Updated1 03/19/2018
4 123 Updated2 03/19/2018
5 123 Unlocked 03/20/2018
6 123 Updated3 03/20/2018
7 123 Updated4 03/20/2018
Output should be rows with id 5,6,7. What should i use to get this output
you could use an inner join on subselect for max create_date
select * from TABLE
INNER JOIN (
select max(CREATE_DATE) max_date
from TABLE
where Action = 'Unlocked' ) T on t.max_date = TABLE.CREATE_DATE
You need not order the inner query because it will return only one value. You can do it as follows
SELECT * FROM TABLE WHERE id >= (select max(id) from TABLE where ACTION='UNLOCKED' and action_id=123);

How can I select all 2nd to the last transaction

Hi all how can I select all 2nd last transaction.
Transaction log
------------------------------
ID|MemberName|TransactionDate|
------------------------------
1 |Member 1 |1/1/2017 |
------------------------------
2 |Member 1 |1/2/2017 | <- I want to select this transaction
------------------------------
3 |Member 1 |1/3/2017 |This the last transaction of this client
------------------------------
4 |Member 2 |2/1/2017 |
------------------------------
5 |Member 2 |2/2/2017 |<- I want to select this transaction
------------------------------
6 |Member 2 |2/3/2017 |This the last transaction of this client
I want to select all 2nd to the last transaction of all of my clients.
Try ROW_NUMBER() functionality(unless you are using MySQL).
SELECT A.ID, A.MEMBERNAME, A.TRANSACTIONDATE
FROM
(
SELECT ID, MEMBERNAME, TRANSACTIONDATE, ROW_NUMBER() OVER (PARTITION BY MEMBERNAME ORDER BY TRANSACTIONDATE DESC) AS RNUM
FROM TRANSACTION_TABLE
) A
WHERE A.RNUM = 2;
It creates indexing for all entries within each type of Membername and orders the numbering in descending order(meaning the first index represents the latest transactiondate). From this index column, you can give a filter of rnum = 2 for the second last transactiondate.
Select top(1) a.Id,a.MemberName, a.TransactionDate from (select top(2) Id,MemberName,TransactionDate from Transaction_log order by Id desc) as a order by a.Id asc;
Assumed table name to be Transaction_Log.
I hope this worked for you.
I just made use on aggregation and join as shown in the query below:
SELECT A.* FROM TRANSACTION_LOG A INNER JOIN
(SELECT MEMBER_NAME, MAX(ID) ID FROM TRANSACTION_LOG
GROUP BY MEMBER_NAME) B
ON A.MEMBER_NAME=B.MEMBER_NAME AND A.ID=B.ID-1;
Here is an SQL Fiddle DEMO

MaxMin Function within Select Statement SQL 2012

I am having a few issues making a MAX function work within the select statement See example data below:
Table 1 Table 2
Visit_ID Car_ID Move_ID Visit_ID MoveStartDate MoveEndDate
A 1 1 A 25/07/2016 27/07/2016
B 2 2 A 28/07/2016 28/07/2016
C 1 3 B 19/07/2016 22/07/2016
D 3 4 D 28/06/2016 30/06/2016
I would like my select statement to pick the min start time and Max start time based on the Visit_ID so I would be expecting:
Result
Visit_ID Car_ID StartDate EndDate
A 1 25/07/2016 28/07/2016
B 2 19/07/2016 22/07/2016
So far I have tried I already have Inner Joins in my select statement:
,(MAX (EndDate) WHERE Visit.Visit_ID = Move.Visit_ID) AS End Date
I have looked at some other queries with a second select statement within the select so you end up with something like:
Select Visit_ID, Car_ID ,(Select MAX(EndDate) FULL OUTER JOIN Table 2 ON Table 1.Visit_ID = Table 2.Visit_ID Group By Table 1.Visit_ID) AS End Date
Hope I have provided enough info currently stumped.
If you also want Car_ID = 3 in the result:
select t1.Visit_ID, t1.Car_ID, MIN(MoveStartDate), MAX(MoveEndDate)
from table1 t1
join table2 t2 on t1.Visit_ID = t2.Visit_ID
group by t1.Visit_ID, t1.Car_ID
Returns:
SQL>select t1.Visit_ID, t1.Car_ID, MIN(MoveStartDate), MAX(MoveEndDate)
SQL&from table1 t1
SQL& join table2 t2 on t1.Visit_ID = t2.Visit_ID
SQL&group by t1.Visit_ID, t1.Car_ID;
visit_id car_id
======== =========== ==================== ====================
A 1 25/07/2016 28/07/2016
B 2 19/07/2016 22/07/2016
D 3 28/06/2016 30/06/2016
3 rows found
I did not check it but your can try this
WITH cte
AS
(select Move_ID,Visit_ID,min(MoveStartDate) AS mMS,MAX(MoveEndDate) AS mME
FROM Table_2
GROUP BY Move_ID,Visit_ID)
SELECT c.Move_ID,c.Visit_ID,T1.Car_ID,c.mMS,c.mME
FROM Table_1 as T1 JOIN cte as C
ON c.Visit_ID=T1.Visit_ID