Comparing sets of values in same table - sql

I'm trying to compare two sets of data in the same table to verify an update operation. I've created this query to view the different sets of information side-by-side, but when I add an additional constraint in the WHERE clause, I get zero rows returned.
The following query shows me the two record sets next to each other, so I can kinda eyeball that there are different componentids:
WITH src AS
(SELECT id AS s_id,
moduleid AS s_moduleid,
instanceid AS s_instanceid,
tagid AS s_tagid,
componentid AS s_componentid
FROM component_junction WHERE id=103)
SELECT * FROM component_junction cj
JOIN src ON s_moduleid=cj.moduleid
AND s_instanceid=cj.instanceid
AND s_tagid=cj.tagid
WHERE cj.id=117
Returns:
id | moduleid | instanceid | tagid | componentid | s_id | s_moduleid | s_instanceid | s_tagid | s_componentid
----|----------|------------|-------|-------------|------|------------|--------------|---------|--------------
117 | 2923 | 7179 | 1 | <null> | 103 | 2923 | 7179 | 1 | <null>
117 | 2923 | 7179 | 2 | <null> | 103 | 2923 | 7179 | 2 | <null>
117 | 2924 | 1404 | 1 | <null> | 103 | 2924 | 1404 | 1 | <null>
117 | 2924 | 1404 | 2 | <null> | 103 | 2924 | 1404 | 2 | <null>
117 | 1 | 41 | 2 | <null> | 103 | 1 | 41 | 2 | 267
117 | 1 | 40 | 2 | <null> | 103 | 1 | 40 | 2 | 267
117 | 1 | 38 | 2 | <null> | 103 | 1 | 38 | 2 | 267
But the below query does not return me any rows. Note the extra AND clause at the end:
WITH src AS
(SELECT id AS s_id,
moduleid AS s_moduleid,
instanceid AS s_instanceid,
tagid AS s_tagid,
componentid AS s_componentid
FROM component_junction WHERE id=103)
SELECT * FROM component_junction cj
JOIN src ON s_moduleid=cj.moduleid
AND s_instanceid=cj.instanceid
AND s_tagid=cj.tagid
WHERE cj.id=117 AND s_componentid != cj.componentid;
I know the values are different since I can see it in the result set from the first query. Some NULL values are present in both sets for componentid so I'd expect those not to show in the second query.

One or both values appear to be NULL. Postgres supports the ANSI standard NULL safe comparison, so change
s_componentid != cj.componentid
to:
s_componentid is distinct from cj.componentid

As one NULL value differs from another NULL value, you may use ISNULL function for ComponentID column like below:
WITH src AS
(SELECT id AS s_id,
moduleid AS s_moduleid,
instanceid AS s_instanceid,
tagid AS s_tagid,
ISNULL(componentid,'') AS s_componentid
FROM component_junction WHERE id=103)
SELECT * FROM component_junction cj
JOIN src ON s_moduleid=cj.moduleid
AND s_instanceid=cj.instanceid
AND s_tagid=cj.tagid
WHERE cj.id=117
AND ISNULL(s_componentid,'') != ISNULL(cj.componentid,'');

Related

new entries by one id

There is a table1 with fields call_id, param0, param1, param2, ...param30 .
The param fields take values ​​from 1 to 100.
And there is a second table table2 with fields call_id, theme_code
which Ineed to fill out from the first table,
The complexity of the task is that for one call_id I need to take each of these param as theme_code,
And if one of the param is null, then you don't need to create a new record for call_id
Example:
table1:
callid | par0 | par1 | par2 | par3 | par4 | par5 | par6 | par7 | par8 | par9 | par10 |
-------------------------------------------------------------------------------------------
1234567 | 24 | 2 | null | 91 | 58 | null | 25 | 19 | 77 | 62 | null |
table2:
callid | theme_code |
------------------------
1234567 | 24 |
------------------------
1234567 | 2 |
------------------------
1234567 | 91 |
------------------------
1234567 | 58 |
------------------------
1234567 | 25 |
------------------------
1234567 | 19 |
------------------------
1234567 | 77 |
------------------------
1234567 | 62 |
You seem to just want to unpivot the columns from table1 into multiple rows:
select callid, theme_code
from table1
unpivot (
theme_code
for par in (par0, par1, par2, par3, par4, par5, par6, par7, par8, par9, par10)
)
CALLID
THEME_CODE
1234567
24
1234567
2
1234567
91
1234567
58
1234567
25
1234567
19
1234567
77
1234567
62
fiddle
You can read more about pivoting and unpivoting in this article.
Unless table1 is some kind of staging table, copying that data into table2 would go against normalisation principles, and you might be better off just using that query when you need it, or creating a view based on it (which could be a materialised view).
If you really do want to put the unpivoted data into another table then you can use that query as the basis for an insert or merge statement.

sql group where clause

I have a table like this:
| grpType | grpId | paramId | val |
|---------|--------|:-------:|------:|
| 0 | 81452 | 123 | 1,293 |
| 0 | 81452 | 127 | 46 |
| 2 | 19873 | 282 | 3 |
| 2 | 19873 | 283 | -10,3 |
| 3 | 81455 | 123 | 1,144 |
| 3 | 100379 | 178 | 40 |
| 3 | 100379 | 188 | 269 |
| 3 | 100379 | 189 | 298 |
| 3 | 100379 | 190 | 267 |
| 3 | 100379 | 191 | 278 |
| 1 | 256 | 188 | 419 |
| 1 | 256 | 189 | 433 |
| 1 | 256 | 190 | 434 |
| 1 | 256 | 191 | 429 |
I want to get data from this table with conditions such as "paramId = 123 and val> = 1.2", "paramId=188 and val<=269", "paramId=189 and val>=298".
Here, since the conditions of "paramId = 188 and val <=269" and "paramId = 189 and val >298" have the same "grpId" in the table, both conditions specified for the "Val" column should provide. In the table above, There are 2 groups that meet the "paramId = 188, paramId = 189" condititon. I have to get the group that provides the requirement of "paramId = 188 and val <=269" and "paramId = 189 and val >298".(so the group of 100379 id)
However, the rows that provide the third condition (paramId = 123 and val >= 1.2) should be added to the data. In the table above, there are two "paramId = 123" row. I have to get the row that provides the requirement of "val >= 1.2".
The "grpType" column is not an important column. You can ignore.
I just need a distinct "grpID" list.
How should the query be I will write?
You can write combination of these conditions use OR in where condition.
Select *
from <TableName>
where ((paramId = 123 and Val >= 1.2) or (paramid=188 and Val <= 269) or (paramid=189 and Val <= 298))
It's like a query will work. If I use intersect, I can't get the rows itself. I can only get common data. It's enough for me now. The number of rows in this table is over 3 million and is constantly increasing. I'm a little worried about performance. I will continue the research.
(select grpId from tableX where paramId=51 and val>=600
intersect
select grpId from tableX where paramId=52 and val<15)
union
(select grpId from tableX where paramId=188 and val<= 269
intersect
select grpId from tableX where paramId=189 and val<= 298)
union
select grpId from tableX where paramId=123 and val<1.29

SQL Question Looking Up Value in Same Table

Trying to use a self join in SQL to look up a value in the table and apply it.
Her's what I got:
+-----------------+-----+--------+-----------+
| Acutal Output | | | |
+-----------------+-----+--------+-----------+
| TRKID | Fac | NewFac | BAG_TRKID |
| 449 | 11 | 11 | 999 |
| 473 | 11 | 11 | 737 |
| 477 | 11 | 11 | 737 |
| 482 | 11 | 11 | 737 |
| 737 | 89 | 89 | |
| Desired Out Put | | | |
| TRKID | Fac | NewFac | BAG_TRKID |
| 449 | 11 | 11 | 999 |
| 473 | 11 | 89 | 737 |
| 477 | 11 | 89 | 737 |
| 482 | 11 | 89 | 737 |
| 737 | 89 | 89 | |
+-----------------+-----+--------+-----------+
Here's the code below. I can't seem to get the table that I want. The Bag TrkID's Facility Num is not becoming the TrkID New Facility Num.
Select
TABLEA.TRKID,
TABLEA.FAC,
NVL(TABLEA.FAC, TABLEB.FAC) as NEWFAC,
TABLEA.BAG_TRKID
FROM
(
Select
HSD. TRKID,
HSD.NLPT as FAC,
SBPD.BAG_TRKID
From
HSD
LEFT JOIN
SBPD
ON
SBPD.BAG_TRKID = HSD. TRKID
Where
HSD.SCANDT BETWEEN ‘Yesterday’ and ‘Today’
) TABLEA
LEFT JOIN
(
Select
HSD. TRKID,
HSD.NLPT as FAC,
SBPD.BAG_TRKID
From
HSD
LEFT JOIN
SBPD
ON
SBPD.BAG_TRKID = HSD. TRKID
Where
HSD.SCANDT BETWEEN ‘Yesterday’ and ‘Today’
) TABLEB
ON
TABLEA.TRKID = TABLEB.BAG_TRKID
Perhaps something like
select a.TrkID, a."Facility Number", a.BAG_TRKID, b.TrkID as "NEW Fac"
from tbl a
left join tbl b on (a.TrkID = b.trk_id_reference)
Given the limited information that you've shared, I was able to achieve the expected output with the following query:
SELECT a.TrkID, a.facility_number, a.bag_trkid, b.facility_number as new_facility_number
FROM test_tbl AS a
LEFT JOIN test_tbl AS b ON a.bag_trkid = b.trkid OR (a.bag_trkid IS NULL AND b.trkid = a.trkid);
You want to get the new_facility_number for a row based on its bag_trkid (which can be achieved by this: LEFT JOIN test_tbl AS b ON a.bag_trkid = b.trkid).
BUT the trick is to account for the cases when the Left Table (which I refer as a) does not have a bag_trkid. In this case, we will keep the new_facility_number to be the same as a.facility_number, joining the tables on the trkid solely: OR (a.bag_trkid IS NULL AND b.trkid = a.trkid)

Getting the top 5 call durations for each phone extention in MS Access

|--------------------------------------------------------------|
| ID. EXT phneNumber duration |
|--------------------------------------------------------------|
| 78172 101 2233379092 00:00:23.0 |
| 78175 104 2233818185 00:08:15.0 |
| 78176 101 9339444840 00:04:56.0 |
| 78177 108 2581594433 00:01:28.0 |
| 78179 104 2533815944 00:02:30.0 |
| 78180 101 2335343977 00:00:00.0 |
| 78181 101 2335343977 00:01:36.0 |
| 78186 108 9229661175 00:00:53.0 |
| 78193 104 2538633408 00:00:00.0 |
| 78194 108 2580013364 00:00:11.0 |
| 78196 104 2583300164 00:00:16.0 |
| 78197 104 9963341189 00:02:44.0 |
| 78198 101 9663319313 00:03:58.0 |
| 78199 101 2104834340 00:03:19.0 |
| 78205 104 2222020401 00:00:00.0 |
|--------------------------------------------------------------|
The table above shows a part of the data in a microsoft Access 2007 database.
EXT is the extension of a phone
phneNumber is the number that was called from that extention
duration is the amount of time that the called lasted
I need to write a query to find the 5 Longest(in duration) calls per extention. The desired result is showed below
|--------------------------------------------------------------|
| ID. EXT phneNumber duration |
|--------------------------------------------------------------|
| 78176 101 9339444840 00:04:56.0 |
| 78198 101 9663319313 00:03:58.0 |
| 78199 101 2104834340 00:03:19.0 |
| 78181 101 2335343977 00:01:36.0 |
| 78172 101 2233379092 00:00:23.0 |
| 78175 104 2233818185 00:08:15.0 |
| 78197 104 9963341189 00:02:44.0 |
| 78179 104 2533815944 00:02:30.0 |
| 78196 104 2583300164 00:00:16.0 |
| 78193 104 2538633408 00:00:00.0 |
| 78177 108 2581594433 00:01:28.0 |
| 78186 108 9229661175 00:00:53.0 |
| 78194 108 2580013364 00:00:11.0 |
|--------------------------------------------------------------|
I tried the below query but is not working as desired and it's very slow as well.
SELECT *
FROM (SELECT DISTINCT ext, phneNumber, duration FROM transactions) t
WHERE t.duration IN ( SELECT TOP 5 duration
FROM transactions
WHERE t.ext = ext
ORDER BY duration desc);
First, I don't see why you are using distinct in the outer from clause. See if this does what you want:
SELECT ext, phneNumber, duration
FROM transactions as t
WHERE t.duration IN ( SELECT TOP 5 t2.duration
FROM transactions t2
WHERE t.ext = t2.ext
ORDER BY t2.duration desc);
TOP in MS Access works differently from top in SQL Server and Sybase, because it returns duplicates. That is, it can return more than five rows if there are duplicates.
If that is an issue, you might try:
SELECT ext, phneNumber, duration
FROM transactions as t
WHERE t.id IN (SELECT TOP 5 t2.id
FROM transactions t2
WHERE t.ext = t2.ext
ORDER BY t2.duration desc, t2.id
);

HOW TO: SQL Server select distinct field based on max value in other field

id tmpname date_used tkt_nr
---|---------|------------------|--------|
1 | template| 04/03/2009 16:10 | 00011 |
2 | templat1| 04/03/2009 16:11 | 00011 |
5 | templat2| 04/03/2009 16:12 | 00011 |
3 | diffname| 03/03/2009 15:11 | 00022 |
4 | diffname| 03/03/2009 16:12 | 00022 |
6 | another | 03/03/2009 16:13 | NULL |
7 | somethin| 24/12/2008 11:12 | 00023 |
8 | name | 01/01/2009 12:12 | 00026 |
I would like to have the result:
id tmpname date_used tkt_nr
---|---------|------------------|--------|
5 | templat2| 04/03/2009 16:12 | 00011 |
4 | diffname| 03/03/2009 16:12 | 00022 |
7 | somethin| 24/12/2008 11:12 | 00023 |
8 | name | 01/01/2009 12:12 | 00026 |
So what I'm looking for is to have distinct tkt_nr values excluding NULL, based on the max value of datetime.
I have tried several options but always failed
SELECT *
FROM templateFeedback a
JOIN (
SELECT ticket_number, MAX(date_used) date_used
FROM templateFeedback
GROUP BY ticket_number
) b
ON a.ticket_number = b.ticket_number AND a.date_used = b.date_used
I would appreciate any help. Unfortunately I need the code to be compatible with SQL Server.
I've stopped doing things this way since I discovered windowing functions. Too often, there are two records with the same timestamp and I get two records in the resultset. Here's the code for tSQL. Similar for Oracle. I don't think mySQL supports this yet.
Select id, tmpname, date_used, tkt_nbr
From
(
Select id, tmpname, date_used, tkt_nbr,
rownum = Row_Number() Over (Partition by tkt_nbr Order by date_used desc)
) x
Where row_num=1