How do you select specific records for each sub record? - sql

Forgive me if im having trouble explaining this. But basically I have:
|Place| Agreement | Open Date | Closed Date | FlagDate
| 1 | a | 1/29/2011 | 7/29/2011 | 2/29/2011
| 1 | b | 2/15/2016 | 7/30/2016 | 2/29/2011
| 1 | c | 3/29/2015 | 8/02/2015 | 2/29/2011
| 2 | d | 4/29/2011 | 7/28/2011 | 6/29/2012
| 2 | e | 5/29/2012 | 7/30/2012 | 6/29/2012
| 3 | f | 6/29/2011 | 8/01/2011 | 7/15/2011
| 3 | g | 7/29/2012 | 8/02/2012 | 7/15/2011
Where there can be multiple Agreements for a single Place. The FlagDate will be the same for each individual Place (ie all of Place 1 has a FlagDate of 2/29/2011)
What I would like to do is simply select the Agreement where the FlagDate falls in between the Open and Close date (the open and close date will never overlap with different agreements.) So the output for the above would be
|Place| Agreement | Open Date | Closed Date | FlagDate
| 1 | a | 1/29/2011 | 7/29/2011 | 2/29/2011
| 2 | e | 5/29/2012 | 7/30/2012 | 6/29/2012
| 3 | f | 6/29/2011 | 8/01/2011 | 7/15/2011

You can use the BETWEEN operator in your WHERE clause to do this:
SELECT * FROM yourtable WHERE flagdate BETWEEN opendate AND closeddate;

Related

Sql server : select members having 2 or more records on different date of same class

I am trying to find out all the member ids who have more than 2 records on a different dates in the same class.
+----------+------------+-------+-----------+
| MemberId | Date | Class | |
+----------+------------+-------+-----------+
| 118111 | 2/18/2020 | A | Valid |
| 118111 | 10/15/2020 | A | Valid |
| 118216 | 1/31/2020 | B | Valid |
| 118216 | 5/16/1981 | B | Valid |
| 118291 | 6/9/2020 | A | Valid |
| 118291 | 12/5/2020 | A | Valid |
| 118533 | 4/9/2020 | A | Not valid |
| 118533 | 11/11/2020 | B | Not valid |
| 118533 | 7/22/2020 | C | Valid |
| 118533 | 10/25/2020 | C | Valid |
| 118293 | 3/30/2020 | A | Not valid |
| 118293 | 3/30/2020 | A | Not valid |
| 118499 | 4/16/2020 | B | Valid |
| 118499 | 7/26/2020 | B | Valid |
| 118499 | 3/25/2020 | A | Not valid |
+----------+------------+-------+-----------+
I have made a query which checks only 2 records but unable to find a solution for checking more than 2 records.
select mc.*
FROM table1 AS mc
JOIN table1 AS ma ON ma.memberid = mc.memberid
AND ma.date != mc.date
AND ma.class = mc.class
Assuming you just want the memberid you can us a HAVING:
SELECT memberid
FROM dbo.YourTable
GROUP BY memberid
HAVING COUNT(DISTINCT [Date]) > 2;

SQL Query - Add column data from another table adding nulls

I have 2 tables, tableStock and tableParts:
tableStock
+----+----------+-------------+
| ID | Num_Part | Description |
+----+----------+-------------+
| 1 | sr37 | plate |
+----+----------+-------------+
| 2 | sr56 | punch |
+----+----------+-------------+
| 3 | sl30 | crimper |
+----+----------+-------------+
| 4 | mp11 | holder |
+----+----------+-------------+
tableParts
+----+----------+-------+
| ID | Location | Stock |
+----+----------+-------+
| 1 | A | 2 |
+----+----------+-------+
| 3 | B | 5 |
+----+----------+-------+
| 5 | C | 2 |
+----+----------+-------+
| 7 | A | 1 |
+----+----------+-------+
And I just want to do this:
+----+----------+-------------+----------+-------+
| ID | Num_Part | Description | Location | Stock |
+----+----------+-------------+----------+-------+
| 1 | sr37 | plate | A | 2 |
+----+----------+-------------+----------+-------+
| 2 | sr56 | punch | NULL | NULL |
+----+----------+-------------+----------+-------+
| 3 | sl30 | crimper | B | 5 |
+----+----------+-------------+----------+-------+
| 4 | mp11 | holder | NULL | NULL |
+----+----------+-------------+----------+-------+
List ALL the rows of the first table and if the second table has the info, in this case 'location' and 'stock', add to the column, if not, just null.
I have been using inner and left join but some rows of the first table disappear because the lack of data in the second one:
select tableStock.ID, tableStock.Num_Part, tableStock.Description, tableParts.Location, tableParts.Stock from tableStock inner join tableParts on tableStock.ID = tableParts.ID;
What can I do?
You can use left join. Here is the demo.
select
s.ID,
Num_Part,
Description,
Location,
Stock
from Stock s
left join Parts p
on s.ID = p.ID
order by
s.ID
output:
| id | num_part | description | location | stock |
| --- | -------- | ----------- | -------- | ----- |
| 1 | sr37 | plate | A | 2 |
| 2 | sr56 | punch | NULL | NULL |
| 3 | sl30 | crimper | B | 5 |
| 4 | mp11 | holder | NULL | NULL |

Generate multiple rows based on a single row containing a null value after a right join

I have a software that retrieve data from multiple devices with SNMP.
The software then create a record in a table with a starting polling time and a ending polling time.
For every SNMP table we retrieve, we put the data in different tables.
In the model below, there is one snmp table (FrequencyValue). The tables are like so:
| Polls | | |
|-------|------------------|------------------|
| id | start_time | end_time |
|-------|------------------|------------------|
| 1 | 2019-04-01T10:00 | 2019-04-01T10:10 |
| 2 | 2019-04-01T11:00 | 2019-04-01T11:10 |
| 3 | 2019-04-01T12:00 | 2019-04-01T12:10 |
| Devices |
|------------|
| ip |
|------------|
| 172.16.1.1 |
| FrequencyValue | | | | |
|----------------|---------|------------------|-----------|-------|
| device_ip | poll_id | timestamp | frequency | value |
|----------------|---------|------------------|-----------|-------|
| 172.16.1.1 | 1 | 2019-04-01T10:02 | 1000 | 10 |
| 172.16.1.1 | 1 | 2019-04-01T10:02 | 2000 | 20 |
| | | | | |
| 172.16.1.1 | 3 | 2019-04-01T12:02 | 1000 | 10 |
| 172.16.1.1 | 3 | 2019-04-01T12:02 | 2000 | 20 |
The problem come when a device fails to answer, because as shown in the table FrequencyValue, the software didn't create a record for that table.
The question: In order to graph the column value per frequency, we would like to create n rows for each frequency that would have the column value to null.
So far, our query look like so:
select p.ip, coalesce(t.timestamp, p.start_time) as "time", t.frequency, t.value
from FrequencyValue as t
right join (
select p.start_time, p.id, d.ip
from Polls as p, Devices as d
) as p on (t.poll_id = p.id and t.device_ip = p.ip)
With output:
| ip | timestamp | frequency | value |
|------------|------------------|-----------|-------|
| 172.16.1.1 | 2019-04-01T10:02 | 1000 | 10 |
| 172.16.1.1 | 2019-04-01T10:02 | 2000 | 20 |
| | | | |
| 172.16.1.1 | 2019-04-01T11:00 | null | null |
| | | | |
| 172.16.1.1 | 2019-04-01T12:02 | 1000 | 10 |
| 172.16.1.1 | 2019-04-01T12:02 | 2000 | 20 |
What we actually want is this:
| ip | timestamp | frequency | value |
|------------|------------------|-----------|-------|
| 172.16.1.1 | 2019-04-01T10:02 | 1000 | 10 |
| 172.16.1.1 | 2019-04-01T10:02 | 2000 | 20 |
| | | | |
| 172.16.1.1 | 2019-04-01T11:00 | 1000 | null |
| 172.16.1.1 | 2019-04-01T11:00 | 2000 | null |
| | | | |
| 172.16.1.1 | 2019-04-01T12:02 | 1000 | 10 |
| 172.16.1.1 | 2019-04-01T12:02 | 2000 | 20 |
We tried putting another right join in the query but we just can't have the result we want.
The frequencies are not defined elsewhere, so to retrieve the frequencies available we could select distinct the frequencies in the table.
The DB is a PostgreSQL.
Use a cross join to generate the rows and then a left join to bring in the values:
select d.ip, t.timestamp, f.frequency, fv.value
from devices d cross join
(select distinct timestamp from frequencyvalue) t cross join
(select distinct frequency from frequencyvalue) f left join
frequencyvalue fv
on fv.device_ip = d.ip and
fv.timestamp = t.timestamp and
fv.frequency = f.frequency;

how to check whether an element in the row exists somewhere in other column but not the same row

I have a SQL table as following
--------------------------
| REPO | USER | FOLLOWER |
--------------------------
| A | 1 | 3 |
| A | 2 | 4 |
| A | 3 | 6 |
| B | 2 | 7 |
| B | 4 | 2 |
| C | 5 | 3 |
| C | 2 | 6 |
| C | 6 | 5 |
--------------------------
Now, I want to only those rows where USER follows another USER for
same REPO.
i.e. I want rows where elements in FOLLOWER is also in USER for same
REPO.
OUTPUT should be like...
--------------------------
| REPO | USER | FOLLOWER |
--------------------------
| A | 1 | 3 |
| B | 4 | 2 |
| C | 6 | 5 |
| C | 2 | 6 |
--------------------------
Thank You :)
One simple method uses exists:
select t.*
from t
where exists (select 1 from t t2 where t2.repo = t.repo and t2.follower = t.user);
Shouldn't the output actually be as follows, i.e. 4 rows?
--------------------------
| REPO | USER | FOLLOWER |
--------------------------
| A | 1 | 3 |
| B | 4 | 2 |
| C | 6 | 5 |
| C | 2 | 6 |
--------------------------

Showing data from another table if it exists

I am having a hard time trying to get the correct data out of my DB.
I have a couple of tables:
events_template laser_events
| id | something | | id | extid | added |
================== ===========================
| 1 | something | | 1 | 7 | added |
| 2 | something | | 2 | 4 | added |
| 3 | something | | 3 | 2 | added |
| 4 | something | | 4 | 1 | added |
| 5 | something | | 5 | 9 | added |
| 6 | something | | 6 | 3 | added |
| 7 | something |
| 8 | something |
| 9 | something |
| 10 | something |
| 11 | something |
| 12 | something |
| 13 | something |
| 14 | something |
What I am trying to do is get some output that will show me the results of both tables together linked by id and extid, but still show the results from events_template even if there isn't a matching laser_events row.
I've tried something like
SELECT
id,
extid
FROM
events_template,
laser_events
WHERE
events_template.id = laser_events.ext_id;
But that doesn't show me the events_template rows if there isn't a matching laser_events row.
Any help would be appreciated!
You have to use LEFT JOIN:
SELECT e.id, l.ext_id
FROM events_template e
LEFT JOIN laser_events l ON e.id = l.ext_id;