How do I join an ARRAY to a COLUMN? - sql

I have two large tables - Table_A and Table_B - that I want to join on the ID field. "ID" in Table_A is a column and "IDs" in Table_B is an array
Table_A:
ID | City |
----+------------+
101 | London |
102 | Paris |
103 | Rome |
104 | Copenhagen |
105 | Amsterdam |
106 | Berlin |
107 | Cardiff |
108 | Lisbon |
Table_B:
Date | Sessions | IDs
------+----------+--------------
06-02 | 1 | [107,102]
06-03 | 1 | [103]
11-12 | 1 | [105,107,103]
27-06 | 1 | [104,108]
31-01 | 1 | [105]
22-04 | 1 | [106,102]
08-07 | 1 | [101,105,108]
02-10 | 1 | [105]
Desirable Output:
Date | Sessions | ID | City
------+----------+-------------+-------------
06-02 | 1 | 107 | Cardiff
| | 102 | Paris
06-03 | 1 | 103 | Rome
11-12 | 1 | 105 | Amsterdam
| | 107 | Cardiff
| | 103 | Rome
27-06 | 1 | 104 | Copenhagen
| | 108 | Lisbon
...
I have tried using inner joins with unnest and union all but nothing is working. Any help would be appreciated.

Something along those lines should yield the result you are looking for
select
date,
sessions,
array_agg(id_un) as id,
array_agg(city) as city
from table_b b, unnest (id) as id_un
left join table_a a on id_un = a.id
group by 1, 2

Consider also below approach
select date, sessions, ids as id,
array(
select city
from b.ids id
left join Table_A
using(id)
) city
from Table_B b
if applied to sample data in your question - output is

Related

match TableA.Id with TableB.Id Than return TableB.Country

I have two tables in my SQLite databaselike this
Table A:
| Id | Date | Rate | Person
|:-- |:-------:| ----:| ------:|
| 1 | 2022-02 | 6.3 | Alex |
| 1 | 2022-05 | 4.2 | John |
| 2 | 2022-09 | 2.5 | Alex |
| 3 | 2022-01 | 7.8 | David |
| 2 | 2022-21 | 9 | William|
Table B:
| Id | City | Country |
|:-- |:---------:| -------:|
| 1 | London | England |
| 2 | Paris | France |
| 3 | Washington| USA |
| 4 | Berlin | Germany |
I need a query to get Id and Rate of each row, in table A then get Country of that Id in Table B
The result should be something like this
Table C:
| Ids | Countries | Rates |
|:--- |:---------:| -----:|
| 1 | England | 6.3 |
| 1 | England | 4.2 |
| 2 | France | 2.5 |
| 3 | USA | 7.8 |
| 2 | France | 9 |
You need to join A and B with Id, and select some columns:
select B.Id as Ids,
B.Country as Countries,
A.Rate as Rates
From A inner join B on(A.Id = B.Id)

SQL Insert multiple value to one key staff from two tables (try to improve)

Basically, I want to insert multiple values to a signal staff form two tables, Value_table and Staff_table, which look like this:
Staff_table
| staff_num | staff_name | staff_role |
+---------------------+------------------+------------------+
| 1 | Bill | 1 |
| 2 | James | 1 |
| 3 | Gina | 2 |
| 4 | Tim | 3 |
Value_table
| value | value_name | value_state |
+------------------+------------------+------------------+
| 123 | Food | 0 |
| 476 | Drink | 1 |
| 656 | Dinner | 1 |
| 77 | Phone | 1 |
And the result should look like this:
| staff_num | value |
+---------------------+------------------+
| 1 | 123 |
| 1 | 476 |
| 1 | 656 |
| 1 | 77 |
| 2 | 123 |
| 2 | 476 |
| 2 | 656 |
| 2 | 77 |
.
.
.
.
I find a SQL way to do it which is the following code.
INSERT INTO Result_table
SELECT DISTINCT a.staff_code, c.func_num
FROM Staff_table a
JOIN Value_table c ON c.value BETWEEN 0 AND 656;
It works but I don't think the last line
JOIN Value_table c ON c.value BETWEEN 0 AND 656;
is a good way to select all the value from the table.
Is there a better way to do it in SQL?
Alternatively you may use CROSS JOIN as
INSERT INTO Result_table
SELECT distinct a.staff_code,c.func_num
FROM Staff_table a
CROSS JOIN Value_table c
Since, there's no need to restrict the value column which is already between 0 and 656 depending on the sample data.
Edit : If you want to restrict add a WHERE condition below as
INSERT INTO Result_table
SELECT distinct a.staff_code,c.func_num
FROM Staff_table a
CROSS JOIN Value_table c
WHERE c.value BETWEEN 77 and 123

Need query for JOIN four tables with some conditions?

I have the following four tables:
1) mls_user
2) mls_category
3) bonus_point
4) mls_entry
In mls_user table values are like below:
*-------------------------*
| id | store_id | name |
*-------------------------*
| 1 | 101 | sandeep |
| 2 | 101 | gagan |
| 3 | 102 | santosh |
| 4 | 103 | manu |
| 5 | 101 | jagveer |
*-------------------------*
In mls_category table values are like below:
*---------------------------------*
| cat_no | store_id | cat_value |
*---------------------------------*
| 20 | 101 | 1 |
| 21 | 101 | 4 |
| 30 | 102 | 1 |
| 31 | 102 | 2 |
| 40 | 103 | 1 |
| 41 | 103 | 1 |
*---------------------------------*
In bonus_point table values are like below:
*-----------------------------------*
| user_id | store_id | bonus_point |
| 1 | 101 | 10 |
| 4 | 101 | 5 |
*-----------------------------------*
In mls_entry table values are like below:
*-------------------------------------------------------*
| user_id | store_id | category | distance | status |
*-------------------------------------------------------*
| 1 | 101 | 20 | 10 | Approved |
| 1 | 101 | 21 | 40 | Approved |
| 1 | 101 | 20 | 10 | Approved |
| 2 | 101 | 20 | 5 | Approved |
| 3 | 102 | 30 | 10 | Approved |
| 3 | 102 | 31 | 80 | Approved |
| 4 | 101 | 20 | 15 | Approved |
*-------------------------------------------------------*
And I want below output:
*--------------------------------------------------*
| user name | Points | bonus Point | Total Point |
*--------------------------------------------------*
| Sandeep | 30 | 10 | 40 |
| Santosh | 30 | 0 | 30 |
| Manu | 15 | 5 | 20 |
| Gagan | 5 | 0 | 5 |
| Jagveer | 0 | 0 | 0 |
*--------------------------------------------------*
I tell the calculation of how the points will come for user Sandeep.
Points = ((10+10)/1 + 40/4)=30
Here 1 and 4 is cat value which comes from mls_category.
I am using below code for a particular user but when i
SELECT sum(t1.totald/c.cat_value) as total_distance
FROM mls_category c
join (
select sum(distance) totald, user_id, category
FROM mls_entry
WHERE user_id=1 AND store_id='101' AND status='approved'
group by user_id, category) t1 on c.cat_no = t1.category
I have created tables in online for checking
DEMO
Computing the points (other than the bonus points) requires a separate join between the mls_entry and mls_category tables. I would do this in a separate subquery, and then join this to the larger query.
Here is one approach:
SELECT
u.name,
COALESCE(t1.points, 0) AS points,
COALESCE(b.bonus_point, 0) AS bonus_points,
COALESCE(t1.points, 0) + COALESCE(b.bonus_point, 0) AS total_points
FROM mls_user u
LEFT JOIN
(
SELECT e.user_id, SUM(e.distance / c.cat_value) AS points
FROM mls_entry e
INNER JOIN mls_category c
ON e.store_id = c.store_id AND e.category = c.cat_no
GROUP BY e.user_id
) t1
ON u.id = t1.user_id
LEFT JOIN bonus_point b
ON u.id = b.user_id
ORDER BY
total_points DESC;
This is the output I am getting from the above query in the demo you setup:
The output does not match exactly, because you have (perhaps) a typo in Santosh's data in your question, or otherwise the expected output in your question has a typo.

Update column with average values in same table using JOIN - SQL Server

I have following table
[Table_01]
ID | Name | Profit | AvgProfit
------------------------------------------
1 | Donald | 1001 |
2 | Hillary | 101 |
3 | Barack | 11 |
4 | Bernie | 1 |
1 | Donald | 1002 |
2 | Hillary | 102 |
3 | Barack | 12 |
4 | Bernie | 2 |
1 | Donald | 1003 |
2 | Hillary | 103 |
3 | Barack | 13 |
4 | Bernie | 3 |
I need to add average Profit value for each person.
Result after UPDATE should be:
[Table_01]
ID | Name | Profit | AvgProfit
------------------------------------------
1 | Donald | 1001 | 1002
2 | Hillary | 101 | 102
3 | Barack | 11 | 12
4 | Bernie | 1 | 1
1 | Donald | 1002 | 1002
2 | Hillary | 102 | 102
3 | Barack | 12 | 12
4 | Bernie | 2 | 1
1 | Donald | 1003 | 1002
2 | Hillary | 103 | 102
3 | Barack | 13 | 12
4 | Bernie | 3 | 1
I do get average values using:
SELECT z1.*, AVG(Profit) OVER(PARTITION BY Name) AVERAGE
FROM Table_01 z1
order by Name
For update I've tried multiple JOIN clauses with no success.
I get various errors: using AGGREGATE in JOIN and invalid object names.
This one works in Oracle, i suppose.
UPDATE Table_01 z1
SET z1.AvgSecs = (SELECT AVG(Profit)
FROM Table_01
WHERE Name = z1.Name)
What is the syntax used in Microsoft SQL Server 2014?
QUESTION 2
I have another table which i need to update
[Table_02]
Name | AvgProfit Name | AvgProfit
--------------------- UPDATE --> ---------------------
Donald | Donald | 1002
Hillary | Hillary | 102
Barack | Barack | 12
Bernie | Bernie | 1
I wonder if this works:
UPDATE t2
SET t2.AvgProfit = t1.AvgProfit
FROM Table_02 t2
join Table_01 t1
ON t1.Name = t2.Name
"Name" is a Unique value
Great thanks for all.
You can use a CTE for the first update:
;WITH CTE AS
(
SELECT Id, AVG(Profit) OVER (PARTITION BY Name) As AvgProfit
FROM Table_01
)
UPDATE T1
SET AvgProfit = CTE.AvgProfit
FROM Table_01 T1
INNER JOIN CTE ON(T1.Id = CTE.Id)
As for your second question - The answer is yes.
Question 1 :
UPDATE Table_01 SET AvgProfit = _AvgProfit FROM
(SELECT ID , AVG(Profit) _AvgProfit FROM Table_01 GROUP BY ID )
A WHERE A.ID = Table_01.ID
Question 2 :
UPDATE Table_02 SET Table_02.AvgProfit = t1.AvgProfit
FROM Table_01 t1 WHERE t1.Name = Table_02.Name

Is it Possible to Join these 2 Tables

I have 2 tables
Table A:
+------------+----------+
| Entry From | Entry To |
+------------+----------+
| 100 | 103 |
| 104 | 105 |
| 106 | 109 |
+------------+----------+
Table B:
+-------+-------+
| Entry | Value |
+-------+-------+
| 100 | 10 |
| 101 | 3 |
| 102 | 7 |
| 103 | 2 |
| 104 | 9 |
| 105 | 17 |
| 106 | 3 |
| 107 | 3 |
| 108 | 6 |
| 109 | 5 |
+-------+-------+
Desired result:
+------------+----------+-------------+
| Entry From | Entry To | Total Value |
+------------+----------+-------------+
| 100 | 103 | 22 |
| 104 | 105 | 26 |
| 106 | 109 | 17 |
+------------+----------+-------------+
Any solutions/advice is welcome.
Thanks to any help in advance!
Please try:
Select
a.EntryFrom, a.EntryTo, sum(Value) TotalValue
From TableA a INNER JOIN TableB b ON b.Entry between a.EntryFrom and a.EntryTo
Group by a.EntryFrom, a.EntryTo
What you're looking for is a subquery maybe.
SELECT
A.Entry_From, A.Entry_To,
(SELECT SUM(B.Value) FROM B
WHERE B.Entry BETWEEN A.Entry_From AND A.Entry_To) AS Total_Value
FROM A
It also depends on what version of SQL so YMMV :)
Here is a working fiddle: http://www.sqlfiddle.com/#!2/afbac/2 using this query:
select a.idxFrom, a.idxTo, sum(b.value) as total
from a inner join b on b.idx >= a.idxFrom and b.idx <= a.idxTo
group by a.idxFrom, a.idxTo