SQL 3 table Join While taking all values from 1 table but only filled from other 2 - sql

I have three tables: the first has a list of category IDs, the second has dataset information, and the third has import information.
What I have
select dataset.pc_id , count(*)
from import
join dataset on CAST (dataset.internal_id as varchar(20)) = import.product_id
group by dataset.pc_id, order by pc_id asc
This will output:
3 4
4 5
6 200
7 192
8 1000
Where product_category comes into play is this: I want the output to look like:
1 0
2 0
3 4
4 5
6 200
...
16 0
The 16 are the number of different product categories from the product_category table that I currently cannot figure out how to fit into that statement.
What is the way to get all the id's from product category into this list with the information joined occupying the result?

Figured it out, needed to get rid of selecting dataset.pc_id and just go with product_category.id and then right join product_category.

Related

Combining related organisation records in SQL where there is a Parent-Child relationship between organisations

I am trying to build a table of data for use in Yellowfin BI reporting. One limitation of this is that no temporary tables can be created and then dropped in the database. I am pulling the data from an existing database, which i have no control over. I can only use SQL to query the existing data.
There are two tables in the source database i need to work with. I've simplified them for clarity. The first contains organisations. It has an ORG_ID column which contains a unique ID for each organisation and a PARENT_ORG_ID column indicating which organisation is the Parent Company of others in the list:
ORG_ID PARENT_ORG_ID
1 Null
2 1
3 5
4 5
5 Null
6 1
Using the table above i can see that there are the following relationships between organisations:
ORG_ID RELATED_ORGANISATIONS
1 2 and 6
2 1 and 6
3 5 and 4
4 5 and 3
5 4 and 3
6 1 and 2
I'm not sure the best way to represent these connections in a query as i need to use these relationships with a second table.
The second table i have is a list of organisations and money owed:
ORG_ID MONEY_OWED
1 5
2 10
3 0
4 15
5 20
6 5
What i need to achieve is a table that i can search for any single ORG_ID, and see the combined data for that Organisation and all related Organisations. In the case of my example, this could be a results table something like this:
ORG_ID MONEY_OWED_BY_ALL_RELATED_ORGS
1 20
2 20
3 35
4 35
5 35
6 20
I'm thinking i should use a CTE to handle the relationships between organisations but i can't get my head around it.
Any help would be greatly appreciated!
For your particular example, you can use:
select o.*,
sum(mo.money_owed) over (partition by coalesce(o.parent_org_id, o.org_id)) as parent_owed
from organizations o left join
money_owed mo
on mo.org_id = o.org_id;
This works because your organizations are only one level deep -- which is consistent with your sample data.

Oracle SQL Count grouped rows in table

I was wonder if it is possible preferably using a select statement on PL/SQL V11 to get the following results from this table:
Area Store Product
10 1 A
10 1 B
11 1 E
11 1 D
10 2 C
10 2 B
10 2 A
10 3 B
10 3 A
13 1 B
13 1 A
and Return this result, so it groups by Area, and Store and looks for and area and store with the same products. So Area 10 Store 1 has products A and B so it will look at the list for other stores that only have A and B and count them. In this example it counts Area 10 store 1/Area 10 store 3/Area 13 Store 1.
Product Count of groups
AB 3
ABC 1
DE 1
Thanks in advance for the help.
Yes, you can use listagg() and then another group by:
select products, count(*)
from (select listagg(product) within group (order by product) as products
from t
group by area, store
) p
group by products;

SQL Calculations With Multi-Group Affiliations

I'm attempting to have a function or view that is able to calculate and roll up various counts while being able to search on a many to many affiliation.
Here is an example data set:
Invoice Table:
InvoiceID LocationID StatusID
1 5 1
2 5 1
3 5 1
4 5 2
5 7 2
5 7 1
5 7 2
Group Table:
GroupID GroupName
1 Group 1
2 Group 2
GroupToLocation Table:
GroupToLocationID GroupID LocationID
1 1 5
2 2 5
3 2 7
I have gotten to the point where I could sum up the various statuses per location and get this:
LocationID Status1 Status2
5 3 1
7 1 2
Location 5 has 3 Invoices with a status of 1, and 1 invoice with a status of 2 while Location 7 has 1 status 1 and 2 status 2
There are two groups, and Location 5 is in both, while Location 7 is only in the second. I need to be able to set it up where I can append a where statement like this:
select * from vw_GroupCounts
where GroupName = 'Group 2'
or
select Invoice, SUM(*) from vw_GroupCounts
where GroupName = 'Group 2'
And that result in only getting Location 7. Whenever I do this, as I have to use left joins or something along those lines, the counts are duplicating for each group the the Location is affiliated with. I know I could do something along the lines of a subquery and pass in the GroupName into that, but the system I am working with uses a dynamic query builder that appends WHERE statements based on user input.
I don't mind using view, or functions, or any number of functions inside of functions, but I hope there is a way to do what I'm looking for.
Since locations 5 and 7 are in Group 2, if you search for group 2 in the where clause after joining all the tables, then you would get all records in this case, this isn't duplication, just the way the data is. A different join wouldn't change this, only changing the data. Let me know if I am misunderstanding something though.
Here is how you would join them to do that search.
Here it is with your first example of the location and status count.

update table with join but with summed values

I've got 2 tables:
-Card
id
points
-History
CardId
points
Now I would like to perform update query which subtracts points in Card table based on points in History with the same cardId
for example I have rows:
-card
1 10
2 30
-History
1 5
1 3
2 10
2 9
and as a result I should have in Card table rows:
-card
1 2
2 11
what is the best way to do that?
This will do it.
update card
set points = points - total
from card
inner join (select cardid, sum(points) as total from history) v
on card.id = v.cardid
But I agree with other comments questioning your database structures

Multiple AVG in single SQL query

I've searched for adding multiple AVG calculations and have found a few entries, however I'm having to join another table and the examples of that are scarce.
closest answer I can find is this
but it deals with dates and no joins
here are my tables:
indicators:
StandardScore IndicatorID NID DID
0.033333 7 1 1
0.907723 9 1 1
0.574739 26 1 1
0.917391 21 1 1
.....
indexindicators:
IndexID IndicatorID
1 7
1 26
2 21
3 7
4 9
4 21
4 7
5 9
.......
My goal is to get the average for each IndexID (indexindicators) related to NID/DID (indicators) combination
a query to retrieve a single value would be
SELECT AVG(StandardScore) FROM `indicators` INNER JOIN indexindicators ON indicators.IndicatorId=indexindicators.IndicatorId WHERE nid=1 AND did=1 AND indexindicators.IndexId=1
ultimately there will be 6 (indexID) averages which then have to be rounded then * by 100 (should I do that part with PHP?)
This seems like such a simple query, but i just can't seem wrap my mind around it.
Thanks in advance for your help!
SELECT nid, did, indexid, 100.0 * AVG(StandardScore)
FROM 'indicators'
INNER JOIN 'indexindicators'
ON indicators.IndicatorId=indexindicators.IndicatorId
group by nid, did, indexid