SQLite join selection from the same table using reference from another table - database

I have two tables:
table: points
|key_id | name | x | y |
------------------------
|1 | A |10 |20 |
|2 | A_1 |11 |21 |
|3 | B |30 |40 |
|4 | B_1 |31 |42 |
table: pairs
|f_key_p1 | f_key_p2 |
----------------------
|1 | 2 |
|3 | 4 |
Table 'pairs' defines which rows in table 'points' should be paired.
How can I query database to select paired rows?
My desired query result would be like this:
|name_1|x_1|x_2|name_2|x_2|y_2|
-------------------------------
|A |10 |20 |A_1 |11 |21 |
|B |30 |40 |B_1 |31 |41 |

You just join from points to pairs and from pairs again to points. E.g. like this:
SELECT
p1.name AS name_1, p1.x AS x_1, p1.y AS y_1,
p2.name AS name_2, p2.x AS x_2, p2.y AS y_2
FROM points as p1
INNER JOIN pairs ON (p1.key_id = pairs.f_key_p1)
INNER JOIN points AS p2 ON (pairs.f_key_p2 = p2.key_id);
Using the INNER JOIN (abbr. JOIN) combines rows only if there is a match in both tables.

select p1.name name_1, p1.x x_1, p1.y y_1, p2.name name_2, p2.x x_2, p2.y y_2
from points p1 join pairs p on p1.key_id = p.f_key_p1
join points p2 on p2.key_id = p.f_key_p2

Related

PostgreSQL filter entity with intermediate table

I would like to create a query, which filters all entities.
Like that ->
FIRST_TABLE
---------------------
|A_ID | TITLE |
|--------------------
|1 | TEST1 |
|2 | TEST2 |
|3 | TEST3 |
|4 | TEST4 |
---------------------
SECOND_TABLE
---------------------
|B_ID | NAME |
|--------------------
|1 | NAME1 |
|2 | NAME2 |
|3 | NAME3 |
|4 | NAME4 |
---------------------
INTERMEDIATE_TABLE
-----------------
|A_FK | B_FK|
|----------------
|2 | 1 |
|2 | 2 |
|2 | 3 |
|3 | 1 |
-----------------
QUERY
SELECT * FROM FIRST_TABLE ft
JOIN INTERMEDIATE_TABLE it
ON ft.A_ID = it.A_FK
WHERE it.B_FK = 1
AND it.B_FK = 2
Then it should only show the entity 2 from first_table because this entity has a relation with NAME1 and NAME2.
How can I make this work?

PostgreSql query to sum all values in json array

I am writing this query for an use case on this table
______________________________________________________
|companyId | detailsJson |
|----------| ----------------------------------------|
|12 |{"dataKeyOne":1.10, "dataKeyTwo":1.20} |
|123 |{"dataKeyFour":2.12, "dataKeySeven":1.18}|
|134 | {} |
|342 | {} |
______________________________________________________
My output coming is after writing this query is :
select companyId, sum(value::float) as sum
from tableA, jsonb_each_text(detailsJson)
group by companyId;
|companyId | sum|
|----------|-------|
|12 | 2.30 |
|123 | 3.30 |
But I want if detailsJson is empty then I want these companyId with 0 sum as shown in table below :
|companyId | sum|
|----------|-------|
|12 | 2.30 |
|123 | 3.30 |
|134 | 0.0 |
|342 | 0.0 |
How can I achieve this using PostgreSQL?
You need to move the jsonb_each_text to the FROM clause so that you can use it in an outer join:
select t.companyid,
sum(d.value::float) as sum
from the_table t
left join jsonb_each_text(t.detailsjson) as d(key, value) on true
group by t.companyid
order by t.companyid
;

How to : update column with sum column in same table in SQL Server 2014?

Before table data:
-----------------------
|ID |WORK|VALUE|TOTAL|
-----------------------
|ID1|WRITE |10 | |
|ID1|TYPE |5 | |
|ID2|READ |25 | |
|ID2|SCAN |30 | |
|ID3|PRINT |15 | |
|ID4|SETTING|20 | |
|ID5|REPAIR |5 | |
|ID5|MAINTE |25 | |
|ID5|MONITOR|20 | |
Total is sum value from same id
ID1 10+5
ID2 25+30
ID3 15
ID4 20
ID5 50
For now I use the insert method with create table data2 (ID,TOTAL)
INSERT INTO DATA2(DATA2.ID, DATA2.TOTAL)
SELECT DATA.ID, SUM (DATA.VALUE) AS TOTAL
FROM DATA
GROUP BY DATA.ID
Then I do SELECT JOIN FROM DATA2 AND DATA
After table data
-----------------------
|ID |WORK|VALUE|TOTAL|
-----------------------
|ID1|WRITE |10 |15 |
|ID1|TYPE |5 |15 |
|ID2|READ |25 |55 |
|ID2|SCAN |30 |55 |
|ID3|PRINT |15 |15 |
|ID4|SETTING|20 |20 |
|ID5|REPAIR |5 |50 |
|ID5|MAINTE |25 |50 |
|ID5|MONITOR|20 |50 |
To update the value total to table, you need to have the column..
alter table tblname
add total int
If this is not a one time approach,i would recommend creating a view like below
create view somename
as
select id,work,value,
sum(value) over (partition by id ) as total
from tabel
if you want to update table as one time excercise
;with cte
as
(select id,work,value,
sum(value) over (partition by id ) as total1
from tablename
)
update t
set t.total=c.total1
from cte c
join tablename t
on t.id=c.id
Another way to update the total.
UPDATE T1
SET T1.TOTAL=T2.TOTAL
FROM YOUT_TABLE T1
JOIN (
SELECT ID,SUM(VALUE) AS TOTAL
FROM YOUR_TABLE
GROUP BY ID
) T2 ON T1.ID=T2.ID
DEMO

How to get the count of each distinct value in Multiple columns and get the result in separate columns?

I need the following table to be queried to get the result given below the table.
Table:
----------------------------------
| Name | Age | slot |
|-------|--------|---------------|
|A |20 | 1 |
|B |30 | 2 |
|C |30 | 1 |
|D |20 | 1 |
|E |40 | 2 |
|F |40 | 3 |
|G |50 | 3 |
----------------------------------
Result:
-------------------------------------------
|Age |Age_Count |Slot |Slot_Count|
-------------------------------------------
|20 | 2 |1 |3 |
-------------------------------------------
|30 | 2 |2 |2 |
-------------------------------------------
|40 | 2 |3 |2 |
-------------------------------------------
|50 | 1 |
-----------------------
While searching stackoverflow i found this question for single column question and there is [this link for multiple columns] (get the count of each distinct value in "Multiple" columns) question. The answers from the second link (for the multiple coulmn's distinct count) is displayed under a single column and my requirement is i guess quite different from the answers posted there.
Thanks in advance
Your request is kind of odd. Are you sure you want that?
If so, this may help:
SET #x:=0,#y:=0,#m:=0,#n:=0;
SELECT
DISTINCT age,age_count, slot,slot_count
FROM (
SELECT
age, age_count, slot, slot_count
FROM (
SELECT
#x:=#x + 1 AS aid, age, COUNT(*) age_count
FROM
slots
GROUP BY age
) a
LEFT JOIN (
SELECT
#y:=#y + 1 AS sid, slot, COUNT(*) slot_count
FROM
slots
GROUP BY slot
) s ON a.aid = s.sid
UNION
SELECT
age, age_count, slot, slot_count
FROM (
SELECT
#m:=#m + 1 AS aid, slot, COUNT(*) slot_count
FROM
slots
GROUP BY slot
) a
LEFT JOIN (
SELECT
#n:=#n + 1 AS sid, age, COUNT(*) age_count
FROM
slots
GROUP BY age
) s ON a.aid = s.sid
) a
If you know for sure that you have more unique ages than unique slots , or opposite, you can get ride of messy union.

Select top n records based on ordinal and attribute data

I have a case where I need to show only the top rows based on a setting in a table and the ordinal set.
Example dataset below shows two customers; each of the customers have a different product.
Since NumRowsToShow is "1" I only want to show one row (the top row based on ordinal) for EACH Customer.
| CustomerID | ProductID | Ordinal | NumRowsToShow |
+------------+-----------+---------+---------------+
| 1 |A |1 |1 |
| 1 |B |2 |1 |
| 1 |C |3 |1 |
| 5 |D |1 |1 |
| 5 |E |2 |1 |
| 5 |F |3 |1 |
The result set after query is run should be
| CustomerID | ProductID |
+------------+-----------+
| 1 |A |
| 5 |D |
In the same scenario if NumRowsToShow were 1 for customerID 1 and 2 for CustomerID 5 I would see something like.
| CustomerID | ProductID | Ordinal | NumRowsToShow |
+------------+-----------+---------+---------------+
| 1 |A |1 |1 |
| 1 |B |2 |1 |
| 1 |C |3 |1 |
| 5 |D |1 |2 |
| 5 |E |2 |2 |
| 5 |F |3 |2 |
The result set after query is run should be
| CustomerID | ProductID |
+------------+-----------+
| 1 |A |
| 5 |D |
| 5 |E |
How can this be done?
Including a screen cap of actual result set with highlights of what I'm trying to filter down to which may be a little helpful.
(source: harpernet.net)
It feels like "cheating in the exams":
SELECT CustomerID, ProductID
FROM tableX
WHERE Ordinal <= NumRowsToShow
If, as comments suggest, the Ordinal can have 10, 20, 30 values and not only 1, ..., n values, then this will work:
SELECT t.CustomerID, t.ProductID
FROM tableX AS t
JOIN tableX AS tt
ON tt.CustomerID = t.CustomerID
AND tt.Ordinal <= t.Ordinal
GROUP BY t.CustomerID
, t.ProductID
, t.NumRowsToShow
HAVING COUNT(*) <= t.NumRowsToShow
or even better, the:
SELECT CustomerID, ProductID
FROM
( SELECT CustomerID, ProductID, NumRowsToShow
, ROW_NUMBER() OVER( PARTITION BY CustomerID
ORDER BY Ordinal
) AS Rn
FROM tableX
) AS tmp
WHERE Rn <= NumRowsToShow ;
Test in: SQL-Fiddle
Your table looks to be not normalized. The NumRowsToShow columns has duplicate infomation and that can lead to update anomalies. This:
| CustomerID | ProductID | Ordinal | NumRowsToShow |
+------------+-----------+---------+---------------+
| 1 |A |1 |1 |
| 1 |B |2 |1 |
| 1 |C |3 |1 |
| 5 |D |1 |2 |
| 5 |E |2 |2 |
| 5 |F |3 |2 |
could be normalized to 2 tables:
| CustomerID | ProductID | Ordinal |
+------------+-----------+---------+
| 1 |A |1 |
| 1 |B |2 |
| 1 |C |3 |
| 5 |D |1 |
| 5 |E |2 |
| 5 |F |3 |
and:
| CustomerID | NumRowsToShow |
+------------+---------------+
| 1 |1 |
| 5 |2 |

Resources