Query that countes pairs with same values depending on third column - sql

I have three columns: Team_Code, ID, times_together.
I'm trying to count how many times ID's have the same "Team_Code" and add times_together to it.
In other words- I'm trying to write all the pairs of one column, check how many times they have the same value in other raw, and add third raw to it.
The simple way to ask this question is picture so:
Values can appear twice (for example
1110 with 8888
and then
8888 with 1110).

You could self join the table on team_code and sum the times_together:
SELECT t1.id, t2.id, SUM(t1.times_together)
FROM mytable t1
JOIN mytable t2 ON t1.team_code = t2.team_code AND t1.id != t2.id
If you want to make sure each pair only appears once, you could add a condition to always take the lower id on the left:
SELECT t1.id, t2.id, SUM(t1.times_together)
FROM mytable t1
JOIN mytable t2 ON t1.team_code = t2.team_code AND t1.id < t2.id

I would suggest this self-joining SQL which takes all possible ID pairs (but only where the first is smaller than the second), and uses a CASE to sum the times_together when the persons played in the same team:
select t1.id,
t2.id,
sum(case when t1.Team_Code = t2.Team_Code
then t1.times_together
else 0
end) times_together
from t as t1
inner join t as t2
on t1.id < t2.id
group by t1.id, t2.id
order by 1, 2
Output in the example case is:
| id | id | times_together |
|------|------|----------------|
| 1028 | 1110 | 0 |
| 1028 | 2220 | 0 |
| 1028 | 8888 | 0 |
| 1110 | 2220 | 1 |
| 1110 | 8888 | 1 |
| 2220 | 8888 | 6 |

Related

Pair record with closest from join

I have the following tables:
id | detected
-----------+----------------
288 | 26817612
288 | 26817734
468 | 26817609
468 | 26817646
476 | 26817700
502 | 26817609
502 | 26817616
502 | 26817655
and
id | fulfilled
-----------+-----------------
288 | 26817616
288 | 26817635
468 | 26817623
468 | 26817659
476 | 26817706
502 | 26817621
502 | 26817627
502 | 26817663
What i need to do, is to JOIN these to tables by id, matching records from the first table, with its closest fulfilled counterpart.
For example:
id | detected | fulfilled
-------------------------
288| 26817612 | 26817616
288| 26817734 | 26817635
468| 26817609 | 26817623
... and so on.
Is there any way to do this with this data, or am i wasting my time and should gather new one?
I have created a solution at DB fiddle with just dataset for Id 288 and it should work for all other Id's as well. Here is the URL https://www.db-fiddle.com/f/vieqapnXDrrGzGeUA7GE5h/4
Here is final sql:
SELECT
s1.Id, s1.detected, s2.fulfilled
FROM
(SELECT
t1.Id, t1.detected, MIN(ABS(t1.detected - t2.fulfilled)) AS Diff
FROM
table1 t1
LEFT JOIN
table2 t2
ON t1.Id = t2.Id
Group by t1.Id, t1.detected) s1
LEFT JOIN
table2 s2
ON s1.Id = s2.Id
WHERE
s1.Diff = ABS(s1.detected - s2.fulfilled)
You seem to want to reduce the number of rows as well. To me, this suggests row_number():
select t12.*
from (select t1.*, t2.*fulfilled
row_number() over (partition by t1.id order by abs(t1.detected - t2.fulfilled)) as seqnum
from t1 join
t2
on t1.id = t2.id
) t12
where seqnum = 1;
One option you have, assuming both tables will always contain the same list of id values, is to use apply() and subtract the two values to get the closest match:
select *
from t1
cross apply(
select top (1) t2.fulfilled
from t2
where t2.id=t1.id
order by Abs(t1.detected-t2.fulfilled)
)t2

SQL - Delete random rows where sum is equal to given number

I want to get some random rows from the given table where the sum is 250(this can be changed). I don`t need to 100% accurate but can be approximate.
Like for 250 (1,5,7)
Note:- My table has huge data.
id | amount|
1 | 96 |
2 | 0.63 |
3 | 351.03 |
4 | 736|
5 | 53 |
6 | 39 |
7 | 105 |
8 | 91 |
For any specific numbers, you can return the closest sum using logic with joins. For instance for 3 numbers -- as in your example:
select t1.*, t2.*, t3.*
from t t1 join
t t2
on t1.id < t2.id join
t t3
on t2.id < t3.id
order by abs(250 - (t1.amount + t2.amount + t3.amount))
fetch first 1 row only;
Note that fetch first is standard SQL. Some databases spell it differently, for instance as limit or select top.

Take data from two tables and show in one row without duplicates with a where condition

I want to take the data from two tables and output them in one row .
output will have two columns "to" and "from" where the condition is "from" will be having data from second table where type is true and "to" column will have data from second table where type is false . FK_ID in second table is linked to ID on the first table . Please help with the query.
I was trying to do with inner joins and union was not able to make it work . Thanks in advance .
TABLE 1
ID | PATH|
1 | ABC |
2 | EFG |
TABLE 2
ID | FK_ID | NUMBER | TYPE
20 | 1 | 123 | TRUE
21 | 1 | 456 | FALSE
28 | 2 | 888 | FALSE
29 | 2 | 939 | TRUE
OUTPUT SHOULD BE:
ID | PATH | TO | FROM
1 | ABC | 456 | 123
2 | EFG | 888 | 939
Use aggregation with pivoting logic to identify the "to" and "from" components of each path:
SELECT
t1.ID,
t1.PATH,
MAX(CASE WHEN t2.TYPE = 'FALSE' THEN t2.NUMBER END) AS "TO",
MAX(CASE WHEN t2.TYPE = 'TRUE' THEN t2.NUMBER END) AS "FROM"
FROM table1 t1
LEFT JOIN table2 t2
ON t1.ID = t2.FK_ID
GROUP BY
t1.ID,
t1.PATH
ORDER BY
t1.ID;
If performance is an issue, you might find a lateral join to be faster:
SELECT t1.*, t2.*
FROM table1 t1 LEFT JOIN LATERAL
(SELECT SUM(T2.NUMBER) FILTER (WHERE NOT t2.TYPE) as num_to,
SUM(T2.NUMBER) FILTER (WHERE t2.TYPE) as num_from
FROM table2 t2
WHERE t1.ID = t2.FK_ID
) t2
ORDER BY t1.ID;
This avoids the outer GROUP BY and probably the sorting as well (assuming that ID is the primary key).
It also assumes that TYPE is a Postgres boolean type. If not, use string comparisons for the WHERE clauses.

Differentiate null and empty in Postgres JOIN query

If I have tables like this:
t1:
id | name
----+------
1 | a
2 | b
3 | c
4 | d
t2:
id | value
----+-------
10 | xxx
20 | yyy
30 | zzz
t_join:
t1_id | t2_id
-------+-------
1 | 10
2 | 20
3 | 30
A SELECT query for t1.id=1 looks like:
SELECT t1.id, t1.name, t2.value FROM t1, t2,t_join WHERE t1.id=t_join.t1_id AND t2.id=t_join.t2_id AND t1.id=1;
And of course returns:
id | name | value
----+------+-------
1 | a | xxx
If I do the same thing with id=4, I get nothing.
SELECT t1.id, t1.name, t2.value FROM t1, t2,t_join WHERE t1.id=t_join.t1_id AND t2.id=t_join.t2_id AND t1.id=4;
id | name | value
----+------+-------
(0 rows)
And, if I do the same thing with a nonsense id=1234132, I also get nothing.
SELECT t1.id, t1.name, t2.value FROM t1, t2,t_join WHERE t1.id=t_join.t1_id AND t2.id=t_join.t2_id AND t1.id=1234132;
id | name | value
----+------+-------
(0 rows)
Is there a way I can differentiate between having an empty result (id=4) vs something that's null (id=1234132)? I guess I want verification that the id I'm checking exists without a separate query. Is this possible?
How about a left join:
SELECT t1.id, t1.name, t2.value
FROM t1 LEFT JOIN
t_join
ON t1.id = t_join.t1_id LEFT JOIN
t2
ON t2.id = t_join.t2_id
WHERE t1.id = 1;
If t.id is not found, you'll get no rows. If there are no matches in t2, then you'll get a NULL value.
Also, a simple rule: Never use commas in the FROM clause. Always, always use proper, explicit JOIN syntax.

Getting all the current effective records from a ORACLE table

I have two tables in oracle database
Table 1 say table1 with fields (id, name)
Records e.g.
###############
id | name
1 | Chair
2 | Table
3 | Bed
###############
and Table 2 say table2 with fields (id, table1_id, date, price)
##############################
id |table1_id| date | price
1 | 1 | 2013-09-09 | 500
2 | 1 | 2013-08-09 | 300
3 | 2 | 2013-09-09 | 5100
4 | 2 | 2013-08-09 | 5000
5 | 3 | 2013-09-09 | 10500
################################
What I want to achieve is to retrieve all the latest price of items from table 2
Result of SQL should be like
##############################
id |table1_id| date | price
1 | 1 | 2013-09-09 | 500
3 | 2 | 2013-09-09 | 5100
5 | 3 | 2013-09-09 | 10500
################################
I am able to run in mysql by following query
SELECT t2.id, t1.id, t1.name, t2.date, t2.price
FROM table1 t1 JOIN table2 t2
ON (t1.id = t2.table1_id
AND t2.id = (
SELECT id
FROM table2
WHERE table1_id = t1.id
ORDER BY table2.date DESC
LIMIT 1
));
but it's not working in ORACLE, Here i Need a query which can run on both server with minor modification
You may try this (shoud work in both MySQL and Oracle):
select t2.id, t2.table1_id, t2.dat, t2.price
from table1 t1 join table2 t2 on (t1.id = t2.table1_id)
join (select table1_id, max(dat) max_date
from table2 group by table1_id) tmax
on (tmax.table1_id = t2.table1_id and tmax.max_date = t2.dat);
This query may return several rows for the same table1_id and date if there are several prices in table2, like this:
##############################
id |table1_id| date | price
1 | 1 | 2013-09-09 | 500
2 | 1 | 2013-09-09 | 300
It's possible to change the query to retrieve only 1 row for each table1_id, but there should be some additional requirements (which row to choose in the above example)
if it doesn't matter then you may try this:
select max(t2.id) as id, t2.table1_id, t2.dat, max(t2.price) as price
from table1 t1 join table2 t2 on (t1.id = t2.table1_id)
join (select table1_id, max(dat) max_date
from table2 group by table1_id) tmax
on (tmax.table1_id = t2.table1_id and tmax.max_date = t2.dat)
group by t2.table1_id, t2.dat;
You can try this using GROUP BY instead, since you're not retrieving the product name from table1 except the product id (which is already in table2)
SELECT id,table1_id,max(date),price
FROM table2
GROUP BY id,table1_id,price
this is what you want :
select t2.id,t2.table1_id,t1.name,t2.pricedate,t2.price
from table1 t1
join
(
select id,table1_id, pricedate,price, row_number() over (partition by table1_id order by pricedate desc) rn
from table2
) t2
on t1.id = t2.table1_id
where t2.rn = 1