SQL Server : creating a table from procedure with selected data - sql

I'm pretty new to SQL Server and been trying to brush up on my skills. I came across this problem today and its stumped me. I can return the products I need but I'm unsure how to create a table using the date/month/name of product from the procedure. If anyone could help or steer me in the right direction that be greatly appreciated.
Data:
CREATE TABLE products
(
id INTEGER NOT NULL PRIMARY KEY,
fruit VARCHAR(30) NOT NULL,
dateBought DATE NOT NULL
);
INSERT INTO products (id, fruit, dateBought) VALUES (0, 'Banana', '2021-07-01');
INSERT INTO products (id, fruit, dateBought) VALUES (1, 'Apple', '2021-06-23');
INSERT INTO products (id, fruit, dateBought) VALUES (2, 'Pear', '2021-01-11');
INSERT INTO products (id, fruit, dateBought) VALUES (3, 'Peach', '2021-08-01');
INSERT INTO products (id, fruit, dateBought) VALUES (4, 'Grape', '2021-08-02');
Executing procedure:
EXEC ProductsBought '2021-07-01'
Expected output:
day month name
----------------------
1 7 Banana
1 8 Peach
My stored procedure:
CREATE PROCEDURE ProductsBought
(#date DATE)
AS
BEGIN
SELECT *
FROM products
WHERE dateBought >= #date
AND dateBought <= DATEADD(MONTH, 1, #date);
END;

I assume you are looking for a resultset to be returned, not actually create a table--two very different things.
To get the date parts of a date, use DATEPART in SQL Server.
Run the following in SSMS:
-- Data mock-up.
DECLARE #products table (
id int NOT NULL PRIMARY KEY,
fruit varchar(30) NOT NULL,
dateBought date NOT NULL
);
INSERT INTO #products VALUES
( 0, 'Banana', '2021-07-01' ),
( 1, 'Apple', '2021-06-23' ),
( 2, 'Pear', '2021-01-11' ),
( 3, 'Peach', '2021-08-01' ),
( 4, 'Grape', '2021-08-02' );
-- Date var.
DECLARE #date date = '07/01/2021';
-- Return resultset.
SELECT
DATEPART ( day, dateBought ) AS [day],
DATEPART ( month, dateBought ) AS [month],
fruit
FROM #products
WHERE
dateBought BETWEEN #date AND DATEADD( month, 1, #date );
Returns
+-----+-------+--------+
| day | month | fruit |
+-----+-------+--------+
| 1 | 7 | Banana |
| 1 | 8 | Peach |
+-----+-------+--------+

You can use below procedure to get what you are looking for:
Create PROCEDURE ProductsBought (#date DATE) AS
BEGIN
SELECT day(datebought)day,month(datebought)Month,fruit name FROM products WHERE dateBought >= #date AND dateBought <= DATEADD(month,1, #date);
END;
Output:
| day | month | name |
----- ------- --------
| 1 | 7 | Banana |
| 1 | 8 | Peach |

Related

Display Average Billing Amount For Each Customer only between years 2019-2021

QUESTION : Display Average Billing Amount For Each Customer ONLY between YEAR(2019-2021).
If customer doesn't have any billing amount for any of the particular year then consider as 0.
-------: OUTPUT :
Customer_ID | Customer_Name | AVG_Billed_Amount
-------------------------------------------------------------------------
1 | A | 87.00
2 | B | 200.00
3 | C | 183.00
--------: EXPLANATION :
If any customer doesn't have any billing records for these 3 years then we need to consider as one record with billing_amount = 0
Like Customer C doesn't have any record for Year 2020, so for C Average will be
(250+300+0)/3 = 183.33 OR 183.00
TEMP TABLE HAS FOLLOWING DATA
DROP TABLE IF EXISTS #TEMP;
CREATE TABLE #TEMP
(
Customer_ID INT
, Customer_Name NVARCHAR(100)
, Billing_ID NVARCHAR(100)
, Billing_creation_Date DATETIME
, Billed_Amount INT
);
INSERT INTO #TEMP
SELECT 1, 'A', 'ID1', TRY_CAST('10-10-2020' AS DATETIME), 100 UNION ALL
SELECT 1, 'A', 'ID2', TRY_CAST('11-11-2020' AS DATETIME), 150 UNION ALL
SELECT 1, 'A', 'ID3', TRY_CAST('12-11-2021' AS DATETIME), 100 UNION ALL
SELECT 2, 'B', 'ID4', TRY_CAST('10-11-2019' AS DATETIME), 150 UNION ALL
SELECT 2, 'B', 'ID5', TRY_CAST('11-11-2020' AS DATETIME), 200 UNION ALL
SELECT 2, 'B', 'ID6', TRY_CAST('12-11-2021' AS DATETIME), 250 UNION ALL
SELECT 3, 'C', 'ID7', TRY_CAST('01-01-2018' AS DATETIME), 100 UNION ALL
SELECT 3, 'C', 'ID8', TRY_CAST('05-01-2019' AS DATETIME), 250 UNION ALL
SELECT 3, 'C', 'ID9', TRY_CAST('06-01-2021' AS DATETIME), 300
-----------------------------------------------------------------------------------
Here, 'A' has 3 transactions - TWICE in year 2020(100+150) and 1 in year 2021(100), but none in 2019(SO, Billed_Amount= 0).
so the average will be calculated as (100+150+100+0)/4
DECLARE #BILL_dATE DATE = (SELECT Billing_creation_date from #temp group by customer_id, Billing_creation_date) /*-- THIS THROWS ERROR AS #BILL_DATE WON'T ACCEPT MULTIPLE VALUES.*/
OUTPUT should look like this:
Customer_ID
Customer_Name
AVG_Billed_Amount
1
A
87.00
2
B
200.00
3
C
183.00
You just need a formula to count the number of missing years.
That's 3 - COUNT(DISTINCT YEAR(Billing_creation_Date)
Then the average = SUM() / (COUNT() + (3 - COUNT(DISTINCT YEAR)))...
SELECT
Customer_ID,
Customer_Name,
SUM(Billed_Amount) * 1.0
/
(COUNT(*) + 3 - COUNT(DISTINCT YEAR(Billing_creation_Date)))
AS AVG_Billed_amount
FROM
#temp
WHERE
Billing_creation_Date >= '2019-01-01'
AND Billing_creation_Date < '2022-01-01'
GROUP BY
Customer_ID,
Customer_Name
Demo : https://dbfiddle.uk/ILcfiGWL
Note: The WHERE clause in another answer here would cause a scan of the table, due to hiding the filtered column behind a function. The way I've formed the WHERE clause allows a "Range Seek" if the column is in an index.
Here is a query that can do that :
select s.Customer_ID, s.Customer_Name, sum(Billed_amount)/ ( 6 - count(1)) as AVG_Billed_Amount from (
select Customer_ID, Customer_Name, sum(Billed_Amount) as Billed_amount
from TEMP
where year(Billing_creation_Date) between 2019 and 2021
group by Customer_ID, year(Billing_creation_Date)
) as s
group by Customer_ID;
According to your description the customer_name C will be 137.5000 not 183.00 since 2018 is not counted and 2020 is not there.

Variable value as column name in Snowflake

can I obtain in a query variable value as column name in Snowflake?
SET "CURRENT_YEAR"=YEAR(CURRENT_DATE());
SELECT SUM("AMOUNT") AS "$CURRENT_YEAR" (here I want the value 2021)
FROM "DB"."SCHEMA"."TABLE"
WHERE YEAR("DATE") = $CURRENT_YEAR;
Please try below:
create or replace table test (
date date,
amount int
);
insert into test values
('2021-01-01', 100),
('2022-01-01', 56),
('2022-02-01', 67),
('2021-05-01', 38),
('2023-01-01', 150),
('2021-01-06', 400),
('2021-07-11', 120)
;
SET "CURRENT_YEAR"=YEAR(CURRENT_DATE());
with year_tbl as (
select year(date) as year, amount from test
where year = $CURRENT_YEAR
)
select *
from year_tbl
pivot(sum(amount) for year in ($CURRENT_YEAR)) as yr
;
+------+
| 2021 |
|------|
| 658 |
+------+
If you want different years:
with year_tbl as (
select year(date) as year, amount from test
)
select *
from year_tbl
pivot(sum(amount) for year in (2020, 2021, 2022, 2023)) as yr
;
+------+------+------+------+
| 2020 | 2021 | 2022 | 2023 |
|------+------+------+------|
| NULL | 658 | 123 | 150 |
+------+------+------+------+
did you mean something like this
create or replace table fld_year as
(SELECT current_date() dt, 2021 as fld_year, 1 as AMT UNION ALL
SELECT current_date(),2021 as fld_year, 2 as r_num UNION ALL
SELECT current_date()- 900,2019 as fld_year, 3 as r_num UNION ALL
SELECT current_date()-400,2020 as fld_year, 4 as r_num );
SET "CURRENT_YEAR"=YEAR(CURRENT_DATE());
SELECT SUM(AMT) FROM fld_year WHERE YEAR(dt) = $CURRENT_YEAR;
SELECT * FROM fld_year WHERE YEAR(dt) = $CURRENT_YEAR;

How to PIVOT multiple columns using SQL Server

I just wrote a query (for SQL Server) that is returning this output:
VendorId
Category
FirstSaleDate
StoreId
1
Car
1/1/2021
12
1
Clothes
1/2/2021
13
1
Toys
1/3/2021
14
1
Food
1/4/2021
15
1
Others
1/5/2021
15
But I actually need the following output
VendorId
Car
StoreId_car
Clothes
StoreId_clothes
Toys
StoreId_toys
Food
StoreId_food
Others
StoreId_others
1
1/1/2021
12
1/2/2021
1/2/2021
1/3/2021
14
1/4/2021
15
1/5/2021
15
I am new to SQL Server, but I saw that this might be possible by using two PIVOTs. I really need your help to find the right syntax.
scenario and output
You just need to pivot twice and combine the results, e.g.:
-- Setup example data...
drop table if exists #Example;
create table #Example (
VendorId int,
Category varchar(10),
FirstSaleDate date,
StoreId int
);
insert #Example (VendorId, [Category], FirstSaleDate, StoreId)
values
(1, 'Car', '2021-01-01', 12),
(1, 'Clothes', '2021-01-02', 13),
(1, 'Toys', '2021-01-03', 14),
(1, 'Food', '2021-01-04', 15),
(1, 'Others', '2021-01-05', 15);
-- Pivot data...
with FirstSales as (
select VendorId, Category, FirstSaleDate from #Example
), Stores as (
select VendorId, 'StoreId_' + Category as Category, StoreId from #Example
)
select
FirstSales.VendorId,
Car, StoreId_Car,
Clothes, StoreId_Clothes,
Toys, StoreId_Toys,
Food, StoreId_Food,
Others, StoreId_Others
from (
select VendorId, Car, Clothes, Toys, Food, Others
from FirstSales
pivot (min(FirstSaleDate) for Category in ([Car], [Clothes], [Toys], [Food], [Others])) as pvt
) as FirstSales
join (
select VendorId, StoreId_Car, StoreId_Clothes, StoreId_Toys, StoreId_Food, StoreId_Others
from Stores
pivot (min(StoreId) for Category in ([StoreId_Car], [StoreId_Clothes], [StoreId_Toys], [StoreId_Food], [StoreId_Others])) as pvt
) as Stores on Stores.VendorId=FirstSales.VendorId;

Get row from date interval even if it doesnt exist from one table

I have this query
SELECT Date, IFNULL(Price, '------') AS Price
FROM productHistory
WHERE Date between '2012-08-15' and '2012-08-19' AND Company='AAA' AND Product='PPP'
GROUP BY Date
and the result is:
Date.......Price
-------------------
2012-08-15...100,00
2012-08-19...110,00
and it should be like this:
Date.........Price
-------------------------------------
2012-08-15......100,00
2012-08-16......--------
2012-08-17......--------
2012-08-18......--------
2012-08-19......110,00
I am working with only one table, I have checked similar quiestions in this forum but I could not find a solution.
When I get this, what I want to do is to add more Companies as columns in the query to get a result like this. well for this I have to change the query..
Date.........PriceCompany1.....PriceCompany2.....PriceCompany3
----------------------------------------------------------
2012-08-15......100,00................................100,00..................................100,0
2012-08-16......---------...............................100,00...................................---------
2012-08-17......---------..............................----------.................................110,00
2012-08-19......110,00..............................100,00..................................----------
What do I need to do?
Create StoredProcedure for that
CREATE PROCEDURE [dbo].[GetMasterData]
#startDate DATETIME,
#endDate DATETIME
AS
BEGIN
SET NOCOUNT ON;
WITH dates(Date) AS
(
SELECT #startdate as Date
UNION ALL
SELECT DATEADD(d,1,[Date])
FROM dates
WHERE DATE < #enddate
)
SELECT Date as Date1 into #tmp1 FROM dates
OPTION (MAXRECURSION 0)
Select Date1,IsNULL(Price, '------') AS Price from #tmp1 left outer join
productHistory on #tmp1.Date1 = productHistory.Date
and Company='AAA' AND Product='PPP'
Drop table #tmp1
END
and execute sp using below line
exec GetMasterData '08/15/2012','08/19/2012'
No need for procedures, just plain SQL will do:
-- generate "pseudo calendar table" from the data:
WITH dt AS (
SELECT DISTINCT zdate FROM producthistory
WHERE zdate between '2012-08-10' and '2012-08-20'
)
-- a poor man's PIVOT:
SELECT dt.zdate
, pa.price AS price_a
, pb.price AS price_b
, pc.price AS price_c
FROM dt
LEFT JOIN producthistory pa ON pa.zdate = dt.zdate AND pa.company='AAA' AND pa.product='ppp'
LEFT JOIN producthistory pb ON pb.zdate = dt.zdate AND pb.company='BBB' AND pb.product='ppp'
LEFT JOIN producthistory pc ON pc.zdate = dt.zdate AND pc.company='CCC' AND pc.product='ppp'
ORDER BY zdate
;
Since the OP does not show any table definition or data, I'll have to invent my own:
CREATE TABLE producthistory
( company varchar
, product varchar
, zdate Date NOT NULL
, price INTEGER
);
INSERT INTO producthistory ( company, product, zdate, price ) VALUES
( 'AAA', 'ppp', '2012-08-15', 100)
, ( 'AAA', 'ppp', '2012-08-15', 110)
, ( 'AAA', 'ppp', '2012-08-15', 120)
, ( 'BBB', 'ppp', '2012-08-16', 200)
, ( 'BBB', 'qqq', '2012-08-16', 210)
, ( 'BBB', 'ppp', '2012-08-16', 220)
, ( 'CCC', 'ppp', '2012-08-15', 300)
;
RESULTS:
CREATE TABLE
INSERT 0 7
zdate | price_a | price_b | price_c
------------+---------+---------+---------
2012-08-15 | 100 | | 300
2012-08-15 | 110 | | 300
2012-08-15 | 120 | | 300
2012-08-16 | | 200 |
2012-08-16 | | 220 |
(5 rows)
adding the IFNULL/COALESCE function (or other formatting trivia) is left as an exercise to the reader

Three column SQL PIVOT

How do I do a sql pivot of data that looks like this, USING the SQL PIVOT command ?
id | field | value
---------------------------------------
1 | year | 2011
1 | month | August
2 | year | 2009
1 | day | 21
2 | day | 31
2 | month | July
3 | year | 2010
3 | month | January
3 | day | NULL
Into something that looks like this:
id | year | month | day
-----------------------------
1 2011 August 21
2 2010 July 31
3 2009 January NULL
Try something like this:
DECLARE #myTable AS TABLE([ID] INT, [Field] VARCHAR(20), [Value] VARCHAR(20))
INSERT INTO #myTable VALUES ('1', 'year', '2011')
INSERT INTO #myTable VALUES ('1', 'month', 'August')
INSERT INTO #myTable VALUES ('2', 'year', '2009')
INSERT INTO #myTable VALUES ('1', 'day', '21')
INSERT INTO #myTable VALUES ('2', 'day', '31')
INSERT INTO #myTable VALUES ('2', 'month', 'July')
INSERT INTO #myTable VALUES ('3', 'year', '2010')
INSERT INTO #myTable VALUES ('3', 'month', 'January')
INSERT INTO #myTable VALUES ('3', 'day', NULL)
SELECT [ID], [year], [month], [day]
FROM
(
SELECT [ID], [Field], [Value] FROM #myTable
) t
PIVOT
(
MIN([Value]) FOR [Field] IN ([year], [month], [day])
) AS pvt
ORDER BY pvt.[year] DESC
Which will yield results of:
ID year month day
1 2011 August 21
3 2010 January NULL
2 2009 July 31
;WITH DATA(id,field,value) AS
(
SELECT 1,'year','2011' UNION ALL
SELECT 1,'month','August' UNION ALL
SELECT 2,'year','2009' UNION ALL
SELECT 1,'day ','21' UNION ALL
SELECT 2,'day ','31' UNION ALL
SELECT 2,'month','July' UNION ALL
SELECT 3,'year','2010' UNION ALL
SELECT 3,'month','January' UNION ALL
SELECT 3,'day ',NULL
)
SELECT id,
year,
month,
day
FROM DATA PIVOT (MAX(value) FOR field IN ([year], [month], [day])) AS Pvt
SELECT
id,
MAX(CASE WHEN RK=3 THEN VAL ELSE '' END) AS "YEAR",
MAX(CASE WHEN RK=2 THEN VAL ELSE '' END) AS "MONTH",
MAX(CASE WHEN RK=1 THEN VAL ELSE '' END) AS "DAY"
FROM
(
SELect
ID,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY YEAR1 ASC) RK,
VAL
FROM TEST3)A
GROUP BY 1
ORDER BY 1;