Select max date No result I want - sql

SELECT
mat.matid,
MAX (to_date(to_char (matdatetable.matdateupdate,'yyyy-mm-dd'),'yyyy-mm-dd')),
mat.matuserid,
mat.matname,
mat.matprice
FROM
matdatetable
LEFT JOIN mat ON matdatetable.sourceid = mat.matid
RESULT
matid matdate update matuserid matname matprice
-------------------------------------------------------------
1 2012-01-01 0:0:0:0 0111-1 aaa 100
1 2012-08-01 0:0:0:0 0111-1 aaa 125
1 2013-08-30 0:0:0:0 0111-1 aaa 150
2 2012-01-01 0:0:0:0 0222-1 bbb 130
2 2012-08-21 0:0:0:0 0222-1 bbb 110
2 2013-07-30 0:0:0:0 0222-1 bbb 100
3 2012-01-01 0:0:0:0 0565-1 ccc 100
3 2013-09-30 0:0:0:0 0565-1 ccc 230
But I want to. Results
matid matdate update matuserid matname matprice
------------------------------------------------------------------
1 2013-08-30 0:0:0:0 0111-1 aaa 150
2 2013-07-30 0:0:0:0 0222-1 bbb 100
3 2013-09-30 0:0:0:0 0565-1 ccc 230

SELECT DISTINCT ON (1)
t.sourceid AS matid
,t.matdateupdate::date AS matdate_update
,m.matuserid
,m.matname
,m.matprice
FROM matdatetable t
LEFT JOIN mat m ON m.matid = t.sourceid
ORDER BY 1, t.matdateupdate DESC;
Gives you the latest (according to matdateupdate) entry per sourceid. Your question isn't clear what you want exactly.
Using sourceid rather than matid, since you have a LEFT JOIN and matid could be NULL. Or your use of LEFT JOIN is incorrect ...
Explanation for DISTINCT ON in this related answer:
Select first row in each GROUP BY group?
t.matdateupdate::date casts your timestamp (assuming for lack of information) to date. That seems to be what you want. If you really need the redundant time 00:00, use datetrunc('day', t.matdateupdate) instead.

Related

How to find overlapping date ranges from same tables (multiple overlapping)

there are user data with data range
I'm trying to update flag section by using query. If same user id group overlap any single day range, it should say overlapping in flag section.
can you please give me some idea how to flag this overlapping data
Thanks
Text file format:
ID UserID registereddate termdate flag
1 abcd 1/1/2018 2/28/2018 overlapping with 2
2 abcd 1/1/2018 6/30/2018 overlapping with 1
3 abcd 8/1/2018 12/31/2018
4 bbbb 5/1/2018 6/30/2018 overlapping with 5
5 bbbb 6/1/2018 7/30/2018 overlapping with 4
6 bbbb 9/1/2018 9/30/2018
7 bbbb 10/1/2018 10/30/2018
8 bbbb 11/1/2018 11/30/2018
9 ccccc 7/1/2018 9/30/2018 overlapping with 10
10 ccccc 9/1/2018 12/31/2018 overlapping with 9
11 dddd 8/1/2018 8/31/2018
12 dddd 12/1/2018 12/31/2018
13 eeee 9/1/2018 12/31/2018 overlapping with 17
14 eeee 8/1/2018 8/31/2018
15 eeee 9/1/2018 9/30/2018 overlapping with 15
To get 'overlapping', use exists:
select t.*,
(case when exists (select 1
from t t2
where t2.registereddate < t.termdate and
t2.termdate > t.registereddate
)
then 'overlaps'
end)
from t;
In an update, this looks like:
update t
set flag = 'overlaps'
where exists (select 1
from t t2
where t2.registereddate < t.termdate and
t2.termdate > t.registereddate
);
Getting the list of overlapping records in a string field is much, much more complicated in SQL Server. Getting a pairwise list of overlaps is pretty easy.
You could also inner join the table onto itself and compare the dates that way
SELECT *
FROM [Table] t1
INNER JOIN [Table] t2
ON t1.ID <> t2.ID
AND t1.UserId = t2.UserId
AND ((t1.RegisterDate BETWEEN t2.RegisterDate AND t2.TermDate) OR (t1.TermDate BETWEEN t2.RegisterDate AND t2.TermDate))
Although the more field you end up having the more complicated this becomes
See this DBFiddle

Find all parent and child with a relationship table

I have inherited two tables:
Table 1: Loc
LocID Field1 Field2
---------------------------
1 AAA BBB
2 CCC DDD
3 EEE FFF
4 GGG HHH
5 III JJJ
6 KKK LLL
7 MMM NNN
8 OOO PPP
9 QQQ RRR
10 SSS TTT
11 UUU VVV
Table 2: LocRel
LocID_A LocID_B
-----------------------
1 2
1 3
2 4
2 5
3 6
3 7
5 11
8 9
8 10
So, the LocRel table basically is used to specified the relationships between the various records in the Loc table.
I am struggling with writing a sql statement that will list all the relationships like so:
LocID Level LocIDH_Ancestry Field1 Field2
---------------------------------------------------
1 1 NULL AAA BBB
2 2 1 CCC DDD
3 2 1 EEE FFF
4 3 1,2 GGG HHH
5 3 1,2 III JJJ
6 3 1,3 KKK LLL
7 3 1,3 MMM NNN
8 1 NULL OOO PPP
9 2 8 QQQ RRR
10 2 8 SSS TTT
11 4 1,2,5 UUU VVV
I am not good at all in queries involving relationships, and would really appreciate some help on how the above can be achieved.
Thank you to all!
This answer may be SQL Server specific. I'm not an expert in SQL, so I don't know how much of this is standard and/or adopted in other dbms.
You can implement the kind of queries you mentioned, using recursive queries. Here is a intro to the subject that provides a good starting point.
For your specific query, something like this should do the work.
WITH MyCTE AS
(
SELECT
LocID, 1 as Level,
NULL as LocIDH_Ancestry,
Field1, Field2
FROM
Table1
WHERE
LocID NOT IN (SELECT LocID_B FROM Table2)
UNION ALL
SELECT
t1.LocID,
c.Level + 1 as Level,
t2.LocID_A as LocIDH_Ancestry,
t1.Field1, t1.Field2
FROM
Table1 t1
INNER JOIN
Table2 t2 ON t1.LocID = t2.LocID_A
INNER JOIN
MyCTE c ON t2.LocID_B = c.LocID
)
SELECT *
FROM MyCTE
Hope that helps.

SQL Merge 3 tables by date where some dates are missing

I have 3 tables that I want to merge, each with a different column of interest. I also have an id variable that I want to do separate merges "within" id. The idea is that I want to merge X, Y, and Z by date (within ID), and have missing values if that date does not exist for a particular variable.
Table X:
ID Date X
1 2012-01-01 101
1 2012-01-02 102
1 2012-01-03 103
1 2012-01-04 104
1 2012-01-05 105
2 2012-01-01 150
Table Y:
ID Date Y
1 2012-01-01 301
1 2012-01-02 302
1 2012-01-03 303
1 2012-01-11 311
2 2012-01-01 350
Table Z:
ID Date Z
1 2012-01-01 401
1 2012-01-03 403
1 2012-01-04 404
1 2012-01-11 411
1 2012-01-21 421
2 2012-01-01 450
Desired Result Table:
ID Date X Y Z
1 2012-01-01 101 301 401
1 2012-01-02 102 302 .
1 2012-01-03 103 303 403
1 2012-01-04 104 . 404
1 2012-01-05 105 . .
1 2012-01-11 . 311 411
1 2012-01-21 . . 421
2 2012-01-01 150 350 450
Any ideas how to write this SQL statement? I've tried messing around with "full joins" and where statements for cross products, but I keep getting duplicate values for some of my ID-date combinations, or sometimes no ID.
Any help would be appreciated.
Joins can be tricky things. My usual approach is to form the set of Keys first, and then use those keys to get what I want.
SELECT source.ID, source.Date, x.X, y.Y, z.Z
FROM
(
SELECT ID, Date
FROM TableX
UNION
SELECT ID, Date
FROM TableY
UNION
SELECT ID, Date
FROM TableZ
) as source
LEFT JOIN TableX x ON source.ID = x.ID AND source.Date = x.Date
LEFT JOIN TableY y ON source.ID = y.ID AND source.Date = y.Date
LEFT JOIN TableZ z ON source.ID = z.ID AND source.Date = z.Date
ORDER BY source.ID, source.Date

SQL Query pivot approach assistance

i am really struggling with this pivot and hoped reaching out for help and enlightenment might help.
Say i have the following table....
Table A
type actId date rowSort order value value_char colName
------------------------------------------------------------------------------------
checking 1003 2011-12-31 2 1 44 44 Amount
checking 1003 2011-12-31 2 2 55 55 Interest
checking 1003 2011-12-31 2 3 66 66 Change
checking 1003 2011-12-31 2 4 77 77 Target
checking 1003 2011-12-31 2 5 88 88 Spread
savings 23456 2011-12-31 1 1 999 999 Amount
savings 23456 2011-12-31 1 2 888 888 Interest
savings 23456 2011-12-31 1 3 777 777 Change
savings 23456 2011-12-31 1 4 666 666 Target
savings 23456 2011-12-31 1 5 555 555 Spread
And i want to transpose to table b
checking chkId date rowSort order chkvalue chkValchar colName savings savId savVal savValChar
-------------------------------------------------------------------------------------------------------------------
checking 1003 2011-12-31 2 1 44 44 Amount savings 23456 999 999
checking 1003 2011-12-31 2 2 55 55 Interest savings 23456 888 888
checking 1003 2011-12-31 2 3 66 66 Change savings 23456 777 777
checking 1003 2011-12-31 2 4 77 77 Target savings 23456 666 666
checking 1003 2011-12-31 2 5 88 88 Spread savings 23456 555 555
I can admit this is beyond my skills at the moment.
I believe i need to do a pivot on this table, using the rowSort (identify savings vs checking) along with ordering using the order column. This maybe wrong and that is why i am here.
Is a pivot the right way to go? Am i right to assume my pivot is to use the aggregate max(rowSort)?
Assuming rowSort from `checking equal to rowSort+1 from savings and the rows link though field value, this should do it:
SELECT DISTINCT
a.type as checking,
a.actId as chkId,
a.date,
a.rowSort+1,
a.order,
a.value as chkvalue,
a.value_char as chkValchar,
a.colName,
b.type as 'savings',
a.actId as savId,
b.value as savVal,
b.value_char as savValChar
FROM tablea a
INNER JOIN tablea b ON b.rowSort = a.rowSort+1 and b.value = a.value
Based on the requirements you presented, you will not use a PIVOT for this query, you will want to JOIN your table to itself. The query below should give you the records that you want without having to use a DISTINCT
select c.type as checking
, c.actId as chkid
, c.date
, c.rowsort
, c.[order]
, c.value as chkvalue
, c.value_char as chkValchar
, c.colName
, s.type as savings
, s.actId as savId
, s.value as savVal
, s.value_char as savValchar
from t1 c
inner join t1 s
on c.rowsort = s.rowsort + 1
and c.[order] = s.[order]
See SQL Fiddle with Demo

MSAccess: Ranking rows based upon column criteria

I have a dataset that looks like this:
Account Cost Centre TransNo
aaa 111 43443
aaa 111 32112
aaa 111 43211
aaa 112 32232
aaa 113 56544
bbb 222 43222
bbb 222 98332
ccc 111 88778
I need a column added that is a counter of the number of rows that relate to that Account/Cost Centre combination:
Account Cost Centre TransNo rCounter
aaa 111 43443 1
aaa 111 32112 2
aaa 111 43211 3
aaa 112 32232 1
aaa 112 56544 2
bbb 222 43222 1
bbb 222 98332 2
ccc 111 88778 1
Is this possible to do in MSAccess using SQL? and how would I go about it (ie what would be the SQL script I would need to write)?
Thanks in advance.
Something like:
SELECT a.Account, a.[Cost Centre], a.TransNo, (SELECT Count(*)
FROM table4 b
WHERE b.Account=a.Account
AND b.[Cost Centre]=a.[Cost Centre]
AND b.TransNo<=a.TransNo) AS AccountNo
FROM Table4 AS a
ORDER BY a.Account, a.[Cost Centre], a.TransNo;