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;
Related
I have a table such as this:
PalmId | UserId | CreatedDate
1 | 1 | 2018-03-08 14:18:27.077
1 | 2 | 2018-03-08 14:18:27.077
1 | 3 | 2018-03-08 14:18:27.077
1 | 1 | 2018-03-08 14:18:27.077
I wish to know how many dates were created for Palm 1 and I also wish to know how many users have created those dates for Palm 1. So the outcome for first is 4 and outcome for second is 3
I am wondering if I can do that in a single query as oppose to having to do a subquery and a join on itself as in example below.
SELECT MT.[PalmId], COUNT(*) AS TotalDates, T1.[TotalUsers]
FROM [MyTable] MT
LEFT OUTER JOIN (
SELECT MT2.[PalmId], COUNT(*) AS TotalUsers
FROM [MyTable] MT2
GROUP BY MT2.[UserId]
) T1 ON T1.[PalmId] = MT.[PalmId]
GROUP BY MT.[PalmId], T1.[TotalUsers]
According to first table you could do something like this:
select count(distinct uerid) as N_Users,
count(created_date) as created_date, -- if you use count(*) you consider also rows with 'NULL'
palmid
from your_table
group by palmid
If you want "4" and "3", then I think you want:
SELECT MT.PalmId, COUNT(*) AS NumRows, COUNT(DISTINCT mt.UserId) as NumUsers
FROM MyTable MT
GROUP BY MT.PalmId
Hi StackOverflow Community,
I'm very new at SQL and I have a question with a problem that I'm having that I don't know how to fix (Btw I'm new at SQL).
So I have these tables:
TABLE 1 - Users
-ID -NAME
1 User1
2 User2
3 User3
TABLE 2 - JOBS
-ID -JOB -USER -ID_DIRECCTION
1 Football Match User1 1
2 Bascketball Match User3 1
3 Swimming Race User2 2
4 Handball Game User3 2
5 Tennis Match User2 3
TABLE 3 - DIRECCTIONS
-ID -DIRECCTION -NUMBER
1 Fail Street 34
2 Swimming Street 45
3 Fake Street 01
What I want to do is to show the Table of Jobs but adding a new column with a SELECT that shows the last user that have been on the direcction (If no one has been in the direcction the result will be null) and if are multiple users the most recent one.
I'm close to get it with my current query (i think), but the main problem is that when I do the subquery there's a way to fetch the inner query with the ID of the current row where's executing the main query??
SELECT j.ID, j.JOB, j.USER, j.ID_DIRECCTION,
(SELECT j.USER
FROM USERS u INNER JOIN
JOBS j
ON j.USER = u.ID INNER JOIN
DIRECCTIONS d
ON d.ID = j.ID_DIRECCTION
WHERE d.ID = (SELECT d.ID FROM DIRECCTIONS WHERE d.ID = j.ID_DIRECCTION --I want this to be current ID_DIRECCTION row)
ORDER BY j.ID DESC FETCH FIRST 1 ROWS ONLY
) AS LAST_USER
FROM JOBS j;
How is the way to select the ID of the current row to fetch other things in subquerys????
The result should be like:
-ID -JOB -USER -ID_DIRECCTION -LAS_TUSER
1 Football Match User1 1 null*
2 Bascketball Match User3 1 User1*
3 Swimming Race User2 2 null*
4 Handball Game User3 2 User2*
5 Tennis Match User2 3 User3*
But I'm always getting the same value in LAST_USER
It seems you want LAG, but it isn't fully clear why LAS_TUSER = User3 for Tennis Match (job id 5)
SELECT j.*,
LAG(u.name)
over (
PARTITION BY j.id_direcction
ORDER BY j.id )
FROM users u
inner join jobs j
ON j.username = u.name
ORDER BY j.id
Demo
It's unclear from your question whether you really have the user name in the jobs table, or just the ID.
If you do have the name then you have all th einformation you need in the jobs table and you can just use lag().
But if you have the ID then you need to join to the users table, for both the current and lag IDs. You can still get the previous ID the same way:
select id, job, id_user, id_direcction,
lag(id_user) over (partition by id_direcction order by id) as last_id_user
from jobs
but then use that as a CTE or inline view, and join from that:
select j.id, j.job, u.name, j.id_direcction, lu.name as last_name
from (
select id, job, id_user, id_direcction,
lag(id_user) over (partition by id_direcction order by id) as last_id_user
from jobs
) j
join users u on u.id = j.id_user
left join users lu on lu.id = j.last_id_user
With CTEs to provide the sample data, and making assumptions about what those really hold:
-- sample data
with users (id, name) as (
select 1, 'User1' from dual
union all select 2, 'User2' from dual
union all select 3, 'User3' from dual
),
jobs (id, job, id_user, id_direcction) as (
select 1, 'Football Match', 1, 1 from dual
union all select 2, 'Bascketball Match', 3, 1 from dual
union all select 3, 'Swimming Race', 2, 2 from dual
union all select 4, 'Handball Game', 3, 2 from dual
union all select 5, 'Tennis Match', 2, 3 from dual
)
-- actual query
select j.id, j.job, u.name, j.id_direcction, lu.name as last_name
from (
select id, job, id_user, id_direcction,
lag(id_user) over (partition by id_direcction order by id) as last_id_user
from jobs
) j
join users u on u.id = j.id_user
left join users lu on lu.id = j.last_id_user
order by j.id;
ID JOB NAME ID_DIRECCTION LAST_
---------- ----------------- ----- ------------- -----
1 Football Match User1 1
2 Bascketball Match User3 1 User1
3 Swimming Race User2 2
4 Handball Game User3 2 User2
5 Tennis Match User2 3
You don't need to refer to the direcctions table unless you want to get its description. I've included a version that does that in this db<>fiddle.
Like #KaushikNayak, I don't see how or why you would expect to see User3 against the last row, based on the data you provided.
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
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
I'm trying to select the first occurrence of record on two conditions but have been in vain. Here's my codes:
PROC SQL;
CREATE TABLE table1 AS
SELECT user_id, type, date, money
FROM table2
WHERE date IN (SELECT MIN(date)
FROM twice_transaction
GROUP BY user_id,type);
For example the original table looks like this(table2)
user type date money
user1 type1 1/10/2012 money1
user1 type1 2/20/2012 money2
user1 type2 1/15/2012 money3
user1 type2 2/30/2012 money4
user2 type1 3/28/2012 money5
user2 type2 2/14/2012 money6
user2 type2 4/13/2012 money7
but I want only: (table1)
user1 type1 1/10/2012 money1
user1 type2 1/15/2012 money3
user2 type1 3/28/2012 money5
user2 type2 2/14/2012 money6
How should I modify/code for my end result? thanks!
There are a couple of ways to do this with SQL. The comment by #NoDisplayName shows you a more traditional SAS way of accomplishing this.
CREATE TABLE table1 AS
SELECT a.user_id, a.type, a.date, a.money
FROM table2 as a
INNER JOIN
SELECT (user_id, type, min(date) as date from table2 group by user_id, type) as b
on a.user_id = b.user_id
and a.type = b.type
and a.date = b.date;
What I am doing here is creating an inner select to get the min date by user_id and type. Then I use an inner join to select only the records from the from the first table that line up with the second.
Use the HAVING clause is also an option.
data have;
informat usert type $8. date mmddyy10. money $8.;
format date date9.;
input usert type date money;
cards;
user1 type1 1/10/2012 money1
user1 type1 2/20/2012 money2
user1 type2 1/15/2012 money3
user1 type2 2/28/2012 money4
user2 type1 3/28/2012 money5
user2 type2 2/14/2012 money6
user2 type2 4/13/2012 money7
;
run;
proc sql;
create table want as
select usert, type, date, money
from have
group by usert, type
having date=min(date);
quit;