Populating fact table - sql

I've a data warehouse for sales, it has 3 dimensions [product,time,store] and a fact table [sales_fact].
Primary key of 'sales_fact' table is made up of all primary keys of dimensions table, dimension tables are all filled up manually now I want to fill 'sales_fact' table with SUM of prices of products stored in a city for a specific month or 3 month period.
How should I sum up prices from product table which are related to a specific month and add it to fact table?

Considering that sum up prices from product table which are related to a specific month
is a measure, your query can be like below :
SELECT DS.City, DT.[Month], SUM(DP.Price)FROM
SalesFact AS S
LEFT JOIN DimProduct AS DP ON DP.ProductSK=S.ProductSK
LEFT JOIN DimTime AS DT ON DT.DateSK=S.DateSK
LEFT JOIN DimStore AS DS ON DS.StoreSK=S.StoreSK
WHERE [Date condition] --Add your date conditoon
GROUP BY DS.City, DT.[Month]
You can use a view for this measure.

Related

SQL Join Table A Column A to Table B Column A or B

I have 2 tables - A Spend Table and a Sales Table
Spend Table Schema:
Spend_ID,
Spend_amount
Sales Table Schema:
Sales_ID_A,
Sales_ID_B,
Sales_amount
I want to do a left join of the spend table to the sales table. The join key from the spend table is the Spend_ID and i want to join when it matches the value in either Sales_ID_A or Sales_ID_B i.e. my match key on the sales table is in 2 columns. So in a way its like applying an 'or' condition to the join on the sales table Sales_ID_A or Sales_ID_B. If a match is found in Sales_ID_A, then no need to check Sales_ID_B. Only check Sales_ID_B if no match is found in Sales_ID_A. How do i achieve this with SQL?
Sample Data Illustration:
See screenshot
The columns called sales_id_a and sales_id_b are actually spend IDs and should better be called spend_id_a and spend_id_b.
You want to join on the first ID, but if that is null, you want to join on the second ID. Use COALESCE for this:
select *
from sales
left join spend on spend.spend_id = coalesce(sales.sales_id_a, sales.sales_id_b)

cross tables query

Let us say we have 2 tables : A and B.
In table A we have payments for customers. 12 payments each year for each customer identified by numClient column and the amount of payment identified by payment column.
In table B there is the sum of payments of the year for every customer so just one row each year per customer still identified by a numClient column and payment identified by yearPayment column.
I would like a query that lists all customers (displaying numClient) whose yearPayment of table B is different from the sum of his payments in table A.
As those tables cover differents years, I would like to query only for 2018. In table A, the payment date is PaymentDate Column. In table B, the year of payment is YearPayment column.
The whole story sounds wrong. Not your words, but the model - why are you using table B? Keep payments where they are (table A). If you have to sum them, do so. Or create a view. But, keeping them separately in two tables just asks for a problem (the one you have now - finding a difference).
Anyway:
select a.id_customer, sum(a.payment), b.sum_payment
from a join b on a.id_customer = b.id_customer
where extract(year from a.date_column) = 2018
and extract(year from b.date_column) = 2018
group by a.id_customer, b.sum_payment
having b.sum_payment <> sum(a.payment)

Creating relationship between tables of different aggregation

I have a retail store data with 50000 records. One of the columns in that file is Segment (Home office, Corporate and Consumer). This data i have in one table. In another table i just have two columns - Segment, Forecast Sales. What query needs to be written to get the actual segment sales and Forecast Sales in single table or how should the relationship be created in SQL.
Data can be found here : https://community.tableau.com/docs/DOC-1236
I will assume table name [Orders] as per your excel and [Segment Forecast] for the table with columns [Segment], [Forecast Sales].
select sf.Segment,sum(o.sales) [Actual Sales],sf.[Forecast Sales]
from [Orders] o
inner join [Segment Forecast] sf on o.Segment=sf.Segment
group by sf.Segment,sf.[Forecast Sales]

Joins on multiple tables to create a view [duplicate]

This question already has answers here:
SQL JOIN and different types of JOINs
(6 answers)
Closed 5 years ago.
I want to create a view by joining three tables.
The schema is a bit complicated, and so for the sake of simplicity, I will mention only the tables and columns required for the problem.
There is a table sales with two columns:
SaleID(pkey),
Buyer,
Amount.
The second table is purchases with two columns:
PurchaseID(pkey),
Seller,
Amount.
I have a third table stockhistory which keeps track of the flow of materials.
The schema of that table is:
Date,
PurchaseID(fkey to column PurchaseID, Purchases Table),
SalesID(fkey to column SalesID, Sales Table),
Amount(calculated amount inserted here).
Now, each of the stockhistory records corresponds to either a record of Purchases table or Sales table, but not both or none.
I have a constraint for that purpose:
([salesid] IS NULL AND [purchaseid] IS NOT NULL OR [salesid] IS NOT NULL AND
[purchaseid] IS NULL)
Now, in the view StockReport, I am trying to pull all records from stockhistory table, and want to display the name of buyer or seller as is the case.
I have tried to write a SQL of the lines of:
SELECT StockHistory.date
, StockHistory.purchaseid
, StockHistory.salesid
, Purchases.seller
, Sales.buyer
WHERE StockHistory.purchaseid = Purchases.purchaseid
OR StockHistory.salesid = Sales.salesid
How can I do the same with LEFT JOIN?
You can use following query
SELECT
SH.date,
SH.purchaseid,
SH.salesid,
P.seller,
S.buyer
FROM stockhistory SH
LEFT JOIN Purchases P on P.PurchaseID=SH.PurchaseID
LEFT JOIN Sales S on S.salesid=SH.salesid

Joining 3 tables & inserting in a 4th table in SQL server

I am joining 3 tables - items , sales , & purchase.
And then, inserting the combined data into a 4th table FULL_DETAIL_OF_ITEMS.
ITEMS table has columns : ITEM_CD, ITEM_NM, COM_CD, SALE_RT, PURCH_RT, MRP
SALES table has columns : ITEM_CD, ITEM_NM, SALE_QTY
PURCHASE table has columns : ITEM_CD, ITEM_NM, PURCH_QTY
FULL_DETAIL_OF_ITEMS table has columns :
ITEM_CD, ITEM_NM, COM_CD, SALE_RT, PURCH_RT, MRP, SALE_QTY, PURCH_QTY
The query is:
insert into FULL_DETAIL_OF_ITEMS
SELECT
Items.Item_CD,
Items.Item_NM ,
ITEMS.COM_CD,
ITEMS.SALE_RT,
ITEMS.PURCH_RT,
ITEMS.MRP,
SALES.SALE_QTY,
PURCHASE.PURCH_QTY
FROM items
JOIN sales on ITEMS.ITEM_CD = sales.ITEM_CD
JOIN purchase on items.ITEM_CD = purchase.ITEM_CD
Items table is filled but sales & purchase tables are empty, so on executing the above query nothing happens? Why so?
At least it should insert rest of the columns from the items table into the 4th table.
It finds that in sales table - sale_qty , & in purchase table, purch_qty is empty, so it should fill null in these columns in the final table & fill rest of the columns as they are picked from item table which consists data so it should fill that.
But its not doing so?
According to the definition of JOIN, ITEM_CD in item table is not matching with the ITEM_CD column of the sales & purchase table as it is empty in both, so this is the reason.
But I want that rest of the data is inserted in the 4th table, then is there any way to do this?
You need to change those join statements to left join.
By default, a join is an "inner join", which means that only rows that exist on both sides of the join will be included. A "left join" includes all rows on the "left" side of the join.
Example:
from items
left join sales on ITEMS.ITEM_CD =sales.ITEM_CD
left join purchase on items.ITEM_CD =purchase.ITEM_CD
You can minimize your query using a select into statement which will, by default, creates a new table at run time.
select Items.Item_CD,Items.Item_NM,Items.COM_CD,Items.Mrp,Items.Purchase_RT,Items.Sale_RT,
purchase.Purchase_QTY,Sales.Sale_QTY
into full_details_of_items
from Items
inner join purchase
inner join Sales
on purchase.Item_CD=Sales.Item_CD
on items.Item_CD=purchase.Item_CD