I'm new to using views, and I'm not exactly sure if what I want to do is possible using a view.
The first table is my original data file that I have imported into SQL.
I created a view with only the fruit and amount_from_us columns, and I'm having trouble figuring out how to include the amount in there. Normally, I'd use a where clause, but I don't know how I can do that at the same time as selecting the other data.
Here is what I have so far:
CREATE VIEW fruit_summary AS
SELECT fruit
, SUM(amount) AS amount
FROM original_table
WHERE bought_from_us = 'yes'
GROUP BY fruit
This gets me the fruit column and the amount_from_us column. I am however lost on how to get the date and total amount in there. Is this even possible using views or should I just create a table and use joins?
Try:
SELECT fruit,
[date],
SUM(amount) AS amount,
SUM(case when bought_from_us = 'yes' then amount else 0 end)
AS amount_from_us
FROM original_table
GROUP BY fruit, [date]
create table #original_table
(
[date] datetime,
fruit varchar(50),
amount money,
bought_from_us char(3)
)
insert #original_table([date], fruit, amount, bought_from_us)
values ('01/18/2012', 'Apple', 10, 0);
insert #original_table([date], fruit, amount, bought_from_us)
values ('01/18/2012', 'Apple', 25, 'yes');
insert #original_table([date], fruit, amount, bought_from_us)
values ('01/18/2012', 'Orange', 32, 0);
insert #original_table([date], fruit, amount, bought_from_us)
values ('01/18/2012', 'Banana', 8, 0);
insert #original_table([date], fruit, amount, bought_from_us)
values ('01/18/2012', 'Banana', 235, 'yes');
insert #original_table([date], fruit, amount, bought_from_us)
values ('01/17/2012', 'Apple', 65, 0);
insert #original_table([date], fruit, amount, bought_from_us)
values ('01/17/2012', 'Apple', 4, 'yes');
insert #original_table([date], fruit, amount, bought_from_us)
values ('01/17/2012', 'Orange', 56, 0);
insert #original_table([date], fruit, amount, bought_from_us)
values ('01/17/2012', 'Orange', 95, 0);
What you've asked for in the result is quite complex. To get the last record, Jan-17 Banana 0 0, you need something like this:
with date_fruit_table as
(
select date_table.[date], fruit_table.fruit
from
(select distinct fruit from #original_table) as fruit_table,
(select distinct [date] from #original_table) as date_table
)
select date_fruit_table.[date], date_fruit_table.fruit,
SUM(isnull(#original_table.amount, 0)) as amount,
SUM(case #original_table.bought_from_us when 'yes' then #original_table.amount else 0 end) as amount_from_us
from date_fruit_table
left outer join #original_table on #original_table.fruit = date_fruit_table.fruit
and #original_table.[date] = date_fruit_table.[date]
group by date_fruit_table.[date], date_fruit_table.fruit
order by date_fruit_table.[date] desc
SELECT fruit
, SUM(amount) AS amount
, SUM(amount_from_us) AS amount_from_us
, [Date]
FROM original_table
WHERE bought_from_us = 'yes'
GROUP BY fruit, [Date]
sorry about my first answer, now I realize what you need:
with CTE_fruit as (
SELECT fruit, date, SUM(amount) AS amount, NULL AS amountUS
FROM original_table
GROUP BY fruit, date
union
SELECT fruit, date, NULL AS amount, SUM(amount) AS amountUS
FROM original_table
WHERE bought_from_us = 'yes'
GROUP BY fruit, date
)
select fruit, date, sum(amount), sum(amountUS) from CTE_fruit
GROUP BY fruit, date
I think this will work
Related
I am attempting to query unique results but am having issues with Query 2 as it pulls the Top 1 result of any ItemNumber instead of my desired ItemNumber from my select statement. I want to display all unique results from Query 1 & I want to display only 1 unique result from Query 2 where NULL Locations are prioritized. (1 'Y' SpecialItem associated per ItemNumber. I have mocked up a small example of my issue to keep the question from being too complex.
Table being used:
CREATE TABLE QA_TESTING (
ItemNumber varchar(255),
ItemName varchar(255),
Location varchar(255)
)
Data being used:
Insert into QA_Testing (ItemNumber, ItemName, Location) Values ('333', 'Apple', 'USA')
Insert into QA_Testing (ItemNumber, ItemName, Location) Values ('501', 'Apple', NULL)
Insert into QA_Testing (ItemNumber, ItemName, Location) Values ('501', 'Apple', NULL)
Insert into QA_Testing (ItemNumber, ItemName, Location) Values ('501', 'Apple', 'USA')
Insert into QA_Testing (ItemNumber, ItemName, Location) Values ('501', 'Apple', NULL)
Insert into QA_Testing (ItemNumber, ItemName, Location) Values ('405', 'Apple', 'USA')
Insert into QA_Testing (ItemNumber, ItemName, Location) Values ('405', 'Orange', 'USA')
Insert into QA_Testing (ItemNumber, ItemName, Location) Values ('501', 'Apple', 'USA')
My View:
IF EXISTS (SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_NAME = N'QA_TESTING_VW')
DROP VIEW QA_TESTING_VW
GO
CREATE VIEW dbo.QA_TESTING_VW
AS
(
(
--Query 1
Select DISTINCT QAT.ItemNumber, QAT.ItemName, Null AS SpecialItem, QAT.Location
From QA_Testing QAT
Where ItemName = 'Apple'
)
UNION ALL
(
--I Want to prioritize to show NULL over a non-null location in second query. If there is a null, show the null, otherwise, show the populated location. Only 1 row should be returned.
--Query 2
Select DISTINCT TOP 1 QAT.ItemNumber, QAT.ItemName, 'Y' AS SpecialItem, QAT.Location
From QA_Testing QAT
Where ItemName = 'Apple'
--ORDER BY Location ASC --ORDER BY TAKES TOO LONG
)
)
GO
My Select Statement:
--This has to stay in a simple format like so, with no additional unions, joins, etc.
Select * from QA_TESTING_VW where ItemNumber in ('501','830')
Outcome:
Expected Outcome:
there is comment "ORDER BY TAKES TOO LONG"
that's why I'm not quite sure.
As fuel for thought:
Select distinct QAT.ItemNumber, QAT.ItemName, O.SpecialItem, QAT.[Location]
From
(
Select QAT.ItemNumber
,QAT.ItemName
,QAT.[Location]
,row_number() over(partition by QAT.ItemNumber, QAT.ItemName order by QAT.[Location]) as LocationPriority
From QA_Testing QAT
Where ItemName = 'Apple'
) QAT
left join
(
select 'Y' AS SpecialItem
union all
select null
) O
on QAT.LocationPriority = 1
I have 2 tables: transactions and transactions_archive. Each of them has fields accountno,drcr(which has values either as C or D) and field amount. I want to get difference of sum of all 'C' in both transactions and transactions_archive and sum of all 'D' in both transactions and transactions_archive.
What query can I use to get this answer.
I tried this unsuccessfully:
select (
select accountno,drcr,sum(amount)as total from
(
select accountno,drcr,amount
from ebank.tbtransactions
where drcr='C'
union all
select accountno,drcr,amount
from ebank.tbtransactions_archive
where drcr='C'
)
)
-
(select accountno,drcr,sum(amount)as total
from (
select accountno,drcr,amount
from ebank.tbtransactions
where drcr='D'
union all
select accountno,drcr,amount
from ebank.tbtransactions_archive
where drcr='D'
)
)
group by accountno,drcr;
If I understand correctly, you want to subtract all the "D"s from the "C"s. Combine the tables using UNION ALL and use conditional aggregation:
select accountno,
sum(case when drcr = 'C' then amount else - amount end)as total
from ((select accountno, drcr, amount
from ebank.tbtransactions
) union all
(select accountno, drcr, amount
from ebank.tbtransactions_archive
)
) t
where drcr in ('D', 'C')
group by accountno;
SELECT top 1 (amount - nextamount) as diff from(
SELECT
amount,LEAD(amount, 1,0) OVER (ORDER BY YEAR(drcr)) AS nextamount FROM(
SELECT drcr, sum(amount) as amount from transactions JOIN transactions_archive on transactions.drcr and transactions_archive.drcr GROUP BY drcr))
I have this query to running value credit with running value
USE tempdb
GO
DROP TABLE TestTable
CREATE TABLE TestTable (ID INT, CREDIT INT,DEBIT INT, TXT NVARCHAR(MAX))
INSERT INTO TestTable (ID, CREDIT,DEBIT,TXT)
SELECT 1, 10,-20,'A' UNION ALL
SELECT 2, 20,-30,'B' UNION ALL
SELECT 3, 30,0,'C' UNION ALL
SELECT 4, 40,0,'C' UNION ALL
SELECT 5, 50,-30,'B' UNION ALL
SELECT 6, 60,0,'A' UNION ALL
SELECT 7, 70,0,'A'
GO
SELECT ID,txt, CREDIT,DEBIT
,SUM(CREDIT) OVER(ORDER BY ID ROWS UNBOUNDED PRECEDING) AS RunningTotal
FROM TestTable AS T
i need this query to sum based on conditions with debit or credit
if txt = 'A' then Running value + credit
if txt = 'B' then Running value + debit
thanks
This works on Oracle :
SELECT SUM(CASE WHEN txt = 'A' THEN CREDIT WHEN txt = 'B' THEN DEBIT END)
FROM TestTable
You might just want a conditional in the sum():
SELECT ID, txt, CREDIT, DEBIT,
SUM(CASE WHEN txt = 'A' THEN CREDIT
WHEN txt = 'B' THEN DEBIT
ELSE 0
END) OVER (ORDER BY ID) AS RunningTotal
FROM TestTable T;
The windows clause is (unbounded preceding) is unnecessary for the cumulative sum. The else 0 is to handle the initial case if txt is neither A nor B. I assume you would want 0.
Essentially I need to group unique product data into a single row when:
The supplier sku matches
The price for the products match (or) 1 of the product lines is equal to '0.00'
Here is a sample dataset set along with a working query for what I'm trying to accomplish. I'm simply not entirely comfortable that this is the best way to perform this query.
DECLARE #Test TABLE
(
SupplierSKU VARCHAR(25),
Description VARCHAR(50),
Quantity VARCHAR(25),
Price VARCHAR(25)
)
INSERT INTO #Test
SELECT '123', 'APPLES', '15', '0.00'
INSERT INTO #Test
SELECT '124', 'ORANGES', '10', '15.34'
INSERT INTO #Test
SELECT '123', 'APPLES', '5', '27.40'
INSERT INTO #Test
SELECT '125', 'PLUMS', '67', '34.86'
INSERT INTO #Test
SELECT '124', 'ORANGES', '10', '15.78'
INSERT INTO #Test
SELECT '125', 'PLUMS', '3', '34.86'
SELECT SupplierSKU, Description, SUM(Quantity) AS [Quantity], MAX(Price) AS [Price]
FROM
(
SELECT SupplierSKU, Description, SUM(CAST(Quantity AS INT)) AS [Quantity], (SELECT MAX(CAST(Price AS MONEY)) AS [Price] FROM #Test ti WHERE ti.SupplierSKU = t.SupplierSKU AND ti.Price = t.price AND ti.Price <> '0.00') AS [Price]
FROM #Test t
GROUP BY SupplierSKU, Description, Price
) pdata
GROUP BY pdata.SupplierSKU, pdata.Description
The desired results:
SupplierSKU Description Quantity Price
123 APPLES 20 27.40
124 ORANGES 10 15.34
124 ORANGES 10 15.78
125 PLUMS 70 34.86
This should produce the "desired output" but the desired output is not consistent with the textual objective. Why are quantity and price varchar. This solution assumes you convert quantity to integer on the SQL table.
SELECT SupplierSKU, Description, SUM(Quantity), P AS [Price]
FROM #test
Where [Price] > 0
GROUP BY SupplierSKU, Description, Price
First I repaired your own solution
SELECT SupplierSKU, Description, SUM(Quantity) AS [Quantity], MAX(cast(Price as money)) AS [Price]
FROM
(
SELECT SupplierSKU, Description, SUM(CAST(Quantity AS INT)) AS [Quantity],
(SELECT MAX(cast(PRICE as money)) from #test
where t.SupplierSKU = SupplierSKU and Description = t.Description and (t.price = '0.00' or t.price = price)) price
FROM #Test t
GROUP BY SupplierSKU, Description , price
) pdata
GROUP BY pdata.SupplierSKU, pdata.Description , price
Then I rewrote your solution to something more readable
SELECT suppliersku, description, sum(cast(quantity as int)) quantity, max(cast(price as money)) price FROM (
SELECT suppliersku, description, quantity, price FROM #test
WHERE price <> '0.00'
UNION ALL
SELECT t1.suppliersku, t1.description, t1.quantity, max(t2.price)
FROM #test t1
join
#test t2 ON t1.SupplierSKU=t2.SupplierSKU and t1.Description = t2.Description
WHERE t1.price = '0.00'
GROUP BY t1.suppliersku, t1.description, t1.quantity
) a
GROUP BY suppliersku, description, price
You may notice i get the right quantity of apples (15+5 = 20)
SELECT SupplierSKU, Description, SUM(Quantity) AS Qte, SUM(Price) AS Total
FROM #test t
GROUP BY SupplierSKU, Description
ORDER BY SupplierSKU
Does that gets you what you want?
I want to write an efficient query which returns a list of fruits by type, the lowest price for the type of fruit and the name of the fruit. Right now, I have a query which return me the fruit type and the lowest price for that type (see below). But I am unable to get the name of the cheapest fruit.
Any idea how I can achieve that? Thanks.
CREATE TABLE Fruits (
[type] nvarchar(250),
[variety] nvarchar(250),
[price] money
)
GO
INSERT INTO Fruits VALUES ('Apple', 'Gala', 2.79)
INSERT INTO Fruits VALUES ('Apple', 'Fuji', 0.24)
INSERT INTO Fruits VALUES ('Apple', 'Limbertwig', 2.87)
INSERT INTO Fruits VALUES ('Orange', 'Valencia', 3.59)
INSERT INTO Fruits VALUES ('Pear', 'Bradford', 6.05)
SELECT type, MIN(price)
FROM Fruits
GROUP BY [type]
Use:
SELECT f.*
FROM FRUITS f
JOIN (SELECT t.type,
MIN(t.price) AS min_price
FROM FRUITS t
GROUP BY t.type) x ON x.type = f.type
AND x.min_price = f.price
I gather you're using SQL Server - if v2005 or newer, you could also use analytic/rank/windowing functions instead:
SELECT f.type, f.variety, f.price
FROM (SELECT t.type, t.variety, t.price,
ROW_NUMBER() OVER (PARTITION BY t.type ORDER BY t.price) AS rank
FROM FRUITS t) f
WHERE f.rank = 1
There are a number of ways to do this, one solution is below.
SELECT F2.type, f2.variety, f2.price
FROM
(
SELECT type, min(price) as price
FROM Fruits
GROUP BY [type]
) as MinData
INNER JOIN Fruits F2
ON (MinData.type = Type = F2.Type
AND MinData.price = F2.Price)
Keep in mind that if you have multiple items in a category with the same price at the minimum you will get multiple results.
There's a simple trick you can use for this sort of query if your table has a surrogate primary key. (Actually, you can do it without one, but it's more convoluted.)
The setup:
if object_id('tempdb..#Fruits') is not null drop table #Fruits
create table #Fruits (
[id] int identity(1,1) not null,
[type] nvarchar(250),
[variety] nvarchar(250),
[price] money
)
insert into #Fruits ([type], [variety], [price])
select 'Apple', 'Gala', 2.79 union all
select 'Apple', 'Fuji', 0.24 union all
select 'Apple', 'Limbertwig', 2.87 union all
select 'Orange', 'Valencia', 3.59 union all
select 'Pear', 'Bradford', 6.05
And now the SQL:
select * -- no stars in PROD!
from #Fruits a
where
a.id in (
select top 1 x.id
from #Fruits x
where x.[type] = a.[type]
order by x.price
)