OraSQL Select Command where multiple entry have same data - sql

I have a table (We call it t_table) with the columns "DATE" and "TIME" (There are more columns, but only these are interesting).
I want my SELECT command to show me only entrys, that have more than one entry with the same combination of "DATE" and "TIME".
example:
Entry | DATE | TIME
1 | 1/1/14 | 8:00
2 | 1/1/14 | 8:00
3 | 2/1/14 | 8:10
4 | 3/1/14 | 8:10
5 | 3/1/14 | 8:10
Should only display me the rows (1+2) + (4+5) because those entrys have the same combination of DATE/TIME in more than one entry.
I'm quite new to SQL so i am relly thankful for every help - Thanks!

You need to check the combination of data(other than the id here) in the table again using EXISTS.
SELECT A.* FROM TABLE A
WHERE EXISTS
(SELECT 'X' FROM TABLE B
WHERE A.DATE = B.DATE
AND A.TIME = B.TIME
AND A.ID <> B.ID)
SQL Fiddle DEMO

If I understand well, it might work with this:
Select a.id,b.id from t_table a, t_table b where a.date=b.date and a.time = b.time;

Related

Joining a large number of tables so that all dates are kept

I have around 50-70 tables that look very similar, say:
Table 1:
id | date | count_A | count_B
1 12.05.2021 12 15
Table 2:
id | date | count_A | count_B
1 15.05.2021 8 24
The main table looks like the following:
id | label
1 X
In the end, what I would like to get is:
id | date | count_A | count_B | label
1 12.05.2021 12 15 X
1 15.05.2021 8 24 X
One intuitive approach is to use the full outer join and join on id but that would result in strange rows with several date values.
Joining on (id, date) doesn't seem to be a great option either.
What can be a possible solution here? Thanks!
You can use a subquery with the statement WITH. Inside this subquery, you can use the UNION with all the tables with the same schema.
Use a join statement between the subquery, in this case tablaC and the main table, which has a different schema.
You can see this example:
WITH tablaC AS (
SELECT ID,date,count_C,Count_D FROM Table_C
UNION ALL
SELECT ID,date,count_C,Count_D FROM Table_D
)
select c.ID,date,c.count_C,c.Count_D,m.label
from tablaC as c
join table_main as m on c.id=m.id

Sql inner join only with last row in second table

I have two tables: leads and tracking_leads.
Table structure is as below,
---------------------------- ----------------------
| leads | | tracking_leads |
---------------------------- ----------------------
| id | | tracking_id |
| lead_id | | lead_id |
| anzahl_tickets | | field_name |
| bearbeitungs_id_einkauf | | date |
---------------------------- -----------------------
I need sql for join table lead with tracking_leads table but get only LAST match row in table tracking_leads .
Sql example:
SELECT DATE_FORMAT(tracking_leads.date, "%d.%m.%Y") as trackDate, SUM(l.anzahl_tickets)
as sumValue FROM leads as l INNER JOIN tracking_leads ON l.lead_id=tracking_leads.lead_id
WHERE bearbeitungs_id_einkauf <> '' AND tracking_leads.field_name='bearbeitungs_id_einkauf'
GROUP BY DATE_FORMAT(tracking_leads.date, "%d.%m.%Y")
In this part : INNER JOIN tracking_leads ON l.lead_id=tracking_leads.lead_id need only last record from tracking_leads table.
For example, leads data:
id lead_id anzahl_tickets bearbeitungs_id_einkauf
1 20 2 100
tracking_leads data:
tracking_id lead_id field_name date
1 20 bearbeitungs_id_einkauf 2019-05-31 13:55
2 20 bearbeitungs_id_einkauf 2019-05-31 15:00
In result i need get :
2019-05-31 2
But now i get
2019-05-31 4
Because there are duplicated of lead_id (need only last record).
How can i solve this problem?
Thanks!
My preference would be to use an inline view to get the max dates.
A correlated subquery would be executed once for each row, while the inline view would only need to be executed once.
This should work:
SELECT DATE_FORMAT(tl.date, "%d.%m.%Y") as trackDate,
SUM(l.anzahl_tickets) as sumValue
FROM leads as l
INNER JOIN (
select x.lead_id, max(x.date) date from tracking_leads x where x.field_name = 'bearbeitungs_id_einkauf' group by x.lead_id
) tl ON l.lead_id=tl.lead_id
WHERE bearbeitungs_id_einkauf <> ''
GROUP BY DATE_FORMAT(tl.date, "%d.%m.%Y")
Side node: the test for empty value of bearbeitungs_id_einkauf in the WHERE clause is database-specific, so watch out for issues there. In Oracle, for example, there is no such thing as an empty string, so you would have to test it for NOT NULL. I'm assuming this is not Oracle.
First, I don't like the date format DD-MM-YYYY, because you cannot sort by it. Just use YYYY-MM-DD.
Second, you can use a correlated subquery to get the most recent date:
SELECT DATE(tl.date) as trackDate, SUM(l.anzahl_tickets) as sumValue
FROM leads l INNER JOIN
tracking_leads tl
ON l.lead_id = tl.lead_id
WHERE l.bearbeitungs_id_einkauf <> '' AND
tl.field_name = 'bearbeitungs_id_einkauf' AND
tl.date = (SELECT MAX(tl2.date)
FROM tracking_leads tl2
WHERE tl2.lead_id = tl.lead_id AND
tl2.field_name = tl.field_name
)
GROUP BY DATE(tl.date);
Of course, you can leave your original date format if you prefer. If you do, you can use:
ORDER BY MIN(tl.date)
so the results are order by the date.

How can I join 3 SQL tables and return latest current date and status?

I have 3 tables:
I'm trying to write a SQL query that joins all 3 tables to return the First and Last Name from Table A, the Status of 1 where there is no 2 logged afterwards and the LogDate (Only want the current day) from table C.
TableA:
UserID | FirstN | LastN |
-------------------------
2324 | John | Doe |
2034 | Jane | Doe |
2946 | Mike | Blank |
TableB:
ViewID | UserID |
-----------------
2315 | 2324 |
8956 | 2034 |
6587 | 2946 |
TableC:
ViewID | LogDate | Status |
-------------------------------------------
2315 | 2017-02-14 11:03:47.000 | 1 |
2315 | 2017-02-14 10:14:47.000 | 2 |
2315 | 2017-02-14 10:00:19.000 | 1 |
In the Status column of TableC, 1 means currently viewing and 2 means done viewing, with LogDate giving the date and time of the Status.
TableA and TableB have the UserID column in common. TableB and TableC have the ViewID column in common.
A person can view a document multiple times in one day so it's possible that the ViewID shows up multiple times in one day with different statuses so I want to return only the most current Status 1 where the user has not finished viewing the document on the current day.
So if you look at TableC, you can see that the same user viewed the document at 2017-02-14 10:00:19.000, then finished at 2017-02-14 10:14:47.000, and then viewed again at 2017-02-14 11:03:47.000. So in this example, I only want the user viewing the document at 2017-02-14 11:03:47.000 because the user has not finished viewing (status did not change to 2 again yet).
I hope I'm making sense in explaining what i'm trying to accomplish....
So, this is what I tried but haven't completely gotten what I want. I can't figure out how to join TableA to get the first and last name and also, stuck trying to get only the current Status of 1 if the user has not finished viewing. It's returning every status of 1 throughout the day.
SELECT
tblb.ViewID,
tblc.LogDate, tblc.Status,
tblb.UserID
FROM
TableB AS tblb
INNER JOIN
TableC AS tblc ON tblb.ViewID = tblc.ViewID
WHERE
LogDate >= CAST(CURRENT_TIMESTAMP AS DATE)
AND LogDate < DATEADD(DD, 1, CAST(CURRENT_TIMESTAMP AS DATE))
AND Status = 1
Assuming it's impossible to have sequence of statuses like (1,1,2) i.e. to open the same doc without closing it first, we need only the last status. So we can figure out the users having open docs and [left] join it to TableA.
SELECT ta.FirstN, ta.LastN, tbc.*
FROM
(SELECT UserID, tblc.*
FROM TableB AS tblb
CROSS APPLY(
SELECT TOP(1) *
FROM TableC AS tblc
WHERE tblb.ViewID = tblc.ViewID
AND LogDate >= CAST(CURRENT_TIMESTAMP AS DATE)
AND LogDate < DATEADD(DD, 1, CAST(CURRENT_TIMESTAMP AS DATE))
ORDER BY LogDate DESC
) tblc
WHERE Status = 1
) tbc
LEFT JOIN TableA ta ON ta.UserID = tbc.UserID;

joins in sql giving me weird results

I have two queries, Q1 and Q2.
Q1 produces one result for each demo and date.
Q2 produces one result for each demo, date and site.
Also, the dates for a given demo and site from Q2 will have some overlap with Q1,
but all dates from Q1 won't be there and there might even be some new dates in Q2 that were not there in Q1.
What I want to do is produce a resulting table that has the results of Q1 basically repeated (rows beneath rows) equal to the number of sites in Q2.
And the results from Q2 should be in the second column with a match on the date and demo.
If a date in Q1 doesn't exist in that site of Q2, the entry should be zero or null. I know this can be achieved with joins, but I can't get it to work. I tried -
select a.result, b.site, b.result from
(Q1) as a right join (Q2) as b on a.demo = b.demo and a.date=b.date
but this is producing some weird results. The entries of a.result are different for each site of Q2 though they shouldn't be.
edit - here is what I'm trying to do -
Q1 -
demo | date
------------------------------
1 | 10/31/2013
1 | 11/01/2013
2 | 11/02/2013
Q2 -
demo | site | date
------------------------------
1 | A | 10/31/2013
1 | A | 11/01/2013
2 | B | 11/01/2013
2 | B | 11/02/2013
desired result -
demo | date | site
---------------------------------------
1 | 10/31/2013 | A
1 | 11/01/2013 | A
2 | 11/02/2013 | null
1 | 10/31/2013 | null
1 | 11/01/2013 | B
2 | 11/02/2013 | B
Use inner join instead of right join
select a.result, b.site, b.result from (Q1) as a
inner join (Q2) as b on a.demo = b.demo and a.date=b.date
Here is an SQL Fiddle example of what I think you are asking for:
SELECT M.demo, M.date, M.site FROM
(
SELECT 2 AS FromQuery, Q2.demo, Q2.date, Q2.site
FROM Q2
UNION
SELECT 1 AS FromQuery, Q1.demo, Q1.date, null AS site
FROM Q1
) AS M
ORDER BY M.FromQuery
Based on your clarification, you could get that result with this query.
SELECT
a.demo,
a.date,
b.site
FROM (Q1) a
LEFT JOIN (Q2) a ON b.date = a.date
Sorting it as you have in your result list would require more information in the subqueries, however. You'd need to use a function like Row_Number() (assuming you're using MSSQL) to generate unique IDs in the sub-queries to use for sorting.

Deleting similar columns in SQL

In PostgreSQL 8.3, let's say I have a table called widgets with the following:
id | type | count
--------------------
1 | A | 21
2 | A | 29
3 | C | 4
4 | B | 1
5 | C | 4
6 | C | 3
7 | B | 14
I want to remove duplicates based upon the type column, leaving only those with the highest count column value in the table. The final data would look like this:
id | type | count
--------------------
2 | A | 29
3 | C | 4 /* `id` for this record might be '5' depending on your query */
7 | B | 14
I feel like I'm close, but I can't seem to wrap my head around a query that works to get rid of the duplicate columns.
count is a sql reserve word so it'll have to be escaped somehow. I can't remember the syntax for doing that in Postgres off the top of my head so I just surrounded it with square braces (change it if that isn't correct). In any case, the following should theoretically work (but I didn't actually test it):
delete from widgets where id not in (
select max(w2.id) from widgets as w2 inner join
(select max(w1.[count]) as [count], type from widgets as w1 group by w1.type) as sq
on sq.[count]=w2.[count] and sq.type=w2.type group by w2.[count]
);
There is a slightly simpler answer than Asaph's, with EXISTS SQL operator :
DELETE FROM widgets AS a
WHERE EXISTS
(SELECT * FROM widgets AS b
WHERE (a.type = b.type AND b.count > a.count)
OR (b.id > a.id AND a.type = b.type AND b.count = a.count))
EXISTS operator returns TRUE if the following SQL statement returns at least one record.
According to your requirements, seems to me that this should work:
DELETE
FROM widgets
WHERE type NOT IN
(
SELECT type, MAX(count)
FROM widgets
GROUP BY type
)