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
Related
I have a table which follows the state of the item delivery:
ID | ContractID | State
----------------------------------
1 | 125 | Created
2 | 125 | Activated
3 | 125 | PickupStarted
4 | 125 | PickedUp
5 | 125 | DeliveryStarted
6 | 125 | Delivered
7 | 126 | Created
8 | 126 | Activated
9 | 126 | PickupStarted
10 | 126 | PickedUp
11 | 126 | DeliveryStarted
12 | 126 | Delivered
13 | 127 | Created
14 | 127 | Activated
15 | 127 | PickupStarted
16 | 127 | PickedUp
I would like to create SQL query which counts only those 'ContractIds' which are not delivered yet (only those whose current status has reached 'PickedUp' status). In this case that would be 'ContractId' 127.
Is there a way to do that type of COUNT()?
You can use not exists:
select count(distinct contractId)
from t
where not exists (select 1
from t t2
where t2.contractId = t.contractid and
t2.status not like 'Deliver%'
);
Or, if you specifically want to get PickedUp as the last status:
select count(*)
from t
where t.id = (select max(t2.id) from t t2 2here t2.contractid = t.contractid) and
t.status = 'PickedUp';
The two are different. The second is specifically that the last status is PickedUp. The first is anyone that has not reached a "deliver" status.
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)
I have 2 tables shown below:
Table 1
Student ID - DATE_NO - SCORE
Table 2
STUDENT_ID - DATE_NO - HT - WT
Table 1 has the physical test scores and the date of the test for each student while Table 2 lists their height (HT) and weight (WT) and the date they were measured.
Example Data:
Table 1
Student ID | DATE_NO | SCORE |
125 | 3 | 90 |
572 | 6 | 75 |
687 | 11 | 95 |
Table 2
Student_ID | DATE_NO | HT | WT |
125 | 2 | 70 | 150 |
125 | 3 | 72 | 155 |
125 | 6 | 72 | 160 |
572 | 2 | 70 | 200 |
572 | 5 | 70 | 225 |
572 | 8 | 70 | 215 |
572 | 9 | 70 | 220 |
687 | 4 | 65 | 140 |
687 | 7 | 67 | 150 |
687 | 11 | 70 | 155 |
687 | 12 | 67 | 160 |
I am not guaranteed to have the exact same DATE_NO for both HT/WT and the Test score date. I want the most recent HT and WT for each student when they took their physical test. Based on the example data above, the optimal join would give me the table below:
Modified Table 1
Student ID | DATE_NO | HT | WT |
125 | 3 | 72 | 155 |
572 | 6 | 70 | 225 |
687 | 11 | 70 | 155 |
I'd like to use the UPDATE statement on Table 1, so after altering Table 1 with HT int and WT int, I attempt to do the following:
UPDATE T1
SET HT = T2.HT, WT = T2.WT
FROM Table_1 as T1
INNER JOIN Table_2 AS T2 ON T1.STUDENT_ID = T2.STUDENT_ID
WHERE (T1.DATE_NO) >= (T2.DATE_NO)
But the result gives me the FIRST record that meets the criteria. Switching greater than to less than [ >= to <= ] Make the HT/WT for each student the entries for Month 6,8, and 12) when it should be month 3,8, and 11. Any suggestions?
FYI: Won't be able to apply any solutions till Friday.
Is it something like this you're looking for:
UPDATE Q
SET
T1_HT = T2_HT
, T1_WT = T2_WT
FROM
(
SELECT
T1.HT T1_HT
, T1.WT T1_WT
, T2.HT T2_HT
, T2.WT T2_WT
, ROW_NUMBER() OVER (PARTITION BY T1.STUDENT_ID ORDER BY T2.DATE_NO DESC) R
FROM
Table_1 T1
JOIN Table_2 T2 ON
T1.STUDENT_ID = T2.STUDENT_ID
AND T2.DATE_NO <= T1.DATE_NO
) Q
WHERE R = 1
SELECT ts.student_id,
ts.date_no,
hw.ht,
hw.wt
FROM test_scores ts,
ht_wt hw
WHERE hw.student_id = ts.student_id
AND hw.date_no <= ts.date_no
AND hw.date_no =
(SELECT max(date_no)
FROM ht_wt
WHERE date_no <= ts.date_no
AND student_id = ts.student_id)
sql fiddle here
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,'');
I have the sql query as below.
(SELECT
height
,width
,ROUND(height / 0.0254, 0) AS "H1"
,FLOOR((width * 2) / 0.0254) AS "W1"
FROM iclr_max_dim_results mdim
,iclr_request req
WHERE mdim.request_oid = req.oid
AND req.request_number = 102017
AND req.version_number = 52731
GROUP BY height
ORDER BY height DESC
) A
)
Below is the result of the query.
height | width | H1 | W1
-----------------------------------------
<hr>
6.0223 | 0.1003 | 237 | 7
6.0198 | 0.2435 | 237 | 19
6.0185 | 0.3151 | 237 | 24
5.9944 | 1.6759 | 236 | 131
5.9931 | 1.6779 | 236 | 132
5.9576 | 1.7016 | 235 | 133
5.9563 | 1.7024 | 235 | 134
If we see the last two columns H1 and W1 in the first three rows, the value 237 repeats with 7, 19, 24 respectively. I will need to return only the rows min and max W1 value for H1.
Here, in this case the result shall be as below. We eliminated 237 | 19 since 7 and 24 are min and max for 237.
6.0223 | 0.1003 | 237 | 7
6.0185 | 0.3151 | 237 | 24
5.9944 | 1.6759 | 236 | 131
5.9931 | 1.6779 | 236 | 132
5.9576 | 1.7016 | 235 | 133
5.9563 | 1.7024 | 235 | 134
How should I edit the SQL qyery to archieve this.
Thank you very much.
Query can be this:
SELECT a.*
FROM (...) a
JOIN (
SELECT H1, MIN(W1) as w1_min, MAX(W1) as w1_max
FROM (...) c
GROUP BY H1
) b ON b.H1 = a.H1 AND (b.w1_min = a.W1 OR b.w1_max = a.W1)
Replace ... with your original query or cretate VIEW from your original query and replace (...) with views name.