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
Related
I have a data table
SQL Fiddle
http://sqlfiddle.com/#!18/b33c86
Schema
create table lenderdata
(
ID int identity
primary key,
LinkID varchar(250) null,
Lender varchar(250) null,
Item varchar(250) null,
Priority int null,
Quantity int null,
Status varchar(250) null
);
INSERT INTO lenderdata (LinkID, Lender, Item, Priority, Quantity, Status) VALUES ('001', 'A', 'Apple', 1, 100, 'PENDING');
INSERT INTO lenderdata (LinkID, Lender, Item, Priority, Quantity, Status) VALUES ('001', 'B', 'Orange', 2, 100, 'PENDING');
INSERT INTO lenderdata (LinkID, Lender, Item, Priority, Quantity, Status) VALUES ('002', 'C', 'Strawberry', 1, 1000, 'PENDING');
INSERT INTO lenderdata (LinkID, Lender, Item, Priority, Quantity, Status) VALUES ('002', 'D', 'grapes', 2, 100, 'PENDING');
INSERT INTO lenderdata (LinkID, Lender, Item, Priority, Quantity, Status) VALUES ('003', 'E', 'coffee', 1, 1000, 'PROCESSING');
INSERT INTO lenderdata (LinkID, Lender, Item, Priority, Quantity, Status) VALUES ('003', 'F', 'mango', 2, 1000, 'PENDING');
I want to group by Link ID and pick up only the one with minimum of priority if the status is PENDING
If the group by data has other status e.g. PROCESSING then it should simply ignore that group
Only if all the status is either PENDING excluding the group if there is one with PROCESSING status
If I was to run the query it would only return Link ID 001 and 002
Your description is hard to make sense of but given your expectation perhaps this is what you require?
select LinkId
from lenderdata
group by LinkId
having Min(status) = 'Pending' and Max(Status) = 'Pending';
You could use the following where clause to filter out any LinkID group that has a status <> 'pending':
WHERE LinkID NOT IN
(
SELECT LinkID FROM lenderdata WHERE Status <> 'PENDING'
)
Now, according to your request: (I want to group by Link ID and pick up only the one with a minimum priority)
If you meant to select rows with a minimum priority for each LinkID group, then you may use the row_number function approach.
WITH CTE AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY LinkID ORDER BY Priority) rn
FROM lenderdata
WHERE LinkID NOT IN
(
SELECT LinkID FROM lenderdata WHERE Status <> 'PENDING'
)
)
SELECT ID, LinkID, Lender, Item, Priority, Quantity, Status
FROM CTE WHERE rn = 1
If you meant to select rows with a minimum priority among all LinkID groups, then you may use the rank function approach.
WITH CTE AS
(
SELECT *,
RANK() OVER (ORDER BY Priority) rnk
FROM lenderdata
WHERE LinkID NOT IN
(
SELECT LinkID FROM lenderdata WHERE Status <> 'PENDING'
)
)
SELECT ID, LinkID, Lender, Item, Priority, Quantity, Status
FROM CTE WHERE rnk = 1
See a demo for your sample data.
See a demo for modified sample data to see the difference between the two approaches (your sample data will get you the same results for both approaches).
I have 3 tables and I am trying to get unique results from all 3 tables (including other columns from each table).
I have tried union approach but that approach only works when I have single column selected from each table.
As soon as I want another corresponding column value from each table, I don't get unique values for the field I am trying to get.
Sample Database and query available here as well: http://www.sqlfiddle.com/#!18/1b9a6/10
Here is the example tables i have created.
CREATE TABLE TABLEA
(
id int,
city varchar(6)
);
INSERT INTO TABLEA ([id], [city])
VALUES
(1, 'A'),
(2, 'B'),
(3, 'C');
CREATE TABLE TABLEB
(
id int,
city varchar(6)
);
INSERT INTO TABLEB ([id], [city])
VALUES
(1, 'B'),
(2, 'C'),
(3, 'D');
CREATE TABLE TABLEC
(
id int,
city varchar(6)
);
INSERT INTO TABLEC ([id], [city])
VALUES
(1, 'C'),
(2, 'D'),
(2, 'E');
Desired result:
A,B,C,D,E
Unique city from all 3 table combined. By unique, I am referring to DISTINCT city from the combination of all 3 tables. Yes, the id is different for common values between tables but it doesn't matter in my use-case if id is coming from table A, B OR C, as long as I am getting DISTINCT (aka UNIQUE) city across all 3 tables.
I tried this query but no luck (city B is missing in the output):
SELECT city, id
FROM
(SELECT city, id
FROM TABLEA
WHERE city NOT IN (SELECT city FROM TABLEB
UNION
SELECT city FROM TABLEC)
UNION
SELECT city, id
FROM TABLEB
WHERE city NOT IN (SELECT city FROM TABLEA
UNION
SELECT city FROM TABLEC)
UNION
SELECT city, id
FROM TABLEC) AS mytable
try this. As this should give you distinct city with there first appear id:
select distinct min(id) over(partition by city) id, city from (
select * from TABLEA
union all
select * from TABLEB
union all
select * from TABLEC ) uni
You got the right idea, just wrap the UNION results in a subquery/temp table and then apply the DISTINCT
WITH TABLEE AS (
SELECT city, id FROM TABLEA
UNION
SELECT city, id FROM TABLEB
UNION
SELECT city, id FROM TABLEC
)
SELECT DISTINCT city
FROM TABLEE
I have several tables containing order information for different items. The customer's may appear multiple times in the different tables. The items are unique to the tables. I would like to create a new table showing all the items a customer purchased in a given year. There should be a column for each item and a binary value indicating if the customer purchased the item that year.
In other words, I would like to convert all the tables listing single item orders (e.g. customer 1 purchased item a in Nov 2007 and item c in May 2007) into yearly transactions (e.g. customer 1 has a transaction for 2007 of {a,c} or [1,0,1,0]). I want to bin the individual orders into yearly transactions so I can mine the association rules.
Minimal Working Example:
Table1 contains orders for items a and b. Table2 contains orders for items c and d.
CREATE TABLE table1
(
orderId INT,
customerId INT,
orderDate DATE,
item VARCHAR(1)
);
CREATE TABLE table2
(
orderId INT,
customerId INT,
orderDate DATE,
item VARCHAR(1)
);
INSERT INTO table1 (orderId, customerId, orderDate, item)
VALUES
('1', '1', '2007-11-11', 'a'),
('2', '2', '2008-3-20', 'b'),
('3', '3','2009-7-11', 'a');
INSERT INTO table2 (orderId, customerId, orderDate, item)
VALUES
('4', '2', '2008-1-1', 'c'),
('5', '1', '2007-5-15', 'c'),
('6', '1', '2009-2-2', 'd');
I am using a union to combine the tables because some order ID's may overlap even though the orders are distinct.
SELECT *
INTO #table3
FROM
(
SELECT *
FROM table1
UNION ALL
SELECT *
FROM table2
) a;
Here is an attempt at the solution but it is not very elegant. More importantly, it does not apply the case statements to each year as desired.
SELECT customerId,
DATEPART(YEAR, orderDate) as orderYear,
CASE
WHEN customerId IN (
SELECT DISTINCT customerId
FROM #table3
WHERE item = 'a')
THEN 1
ELSE 0
END AS itemA,
CASE
WHEN customerId IN (
SELECT DISTINCT customerId
FROM #table3
WHERE item = 'b')
THEN 1
ELSE 0
END AS itemB,
CASE
WHEN customerId IN (
SELECT DISTINCT customerId
FROM #table3
WHERE item = 'c')
THEN 1
ELSE 0
END AS itemC,
CASE
WHEN customerId IN (
SELECT DISTINCT customerId
FROM #table3
WHERE item = 'd')
THEN 1
ELSE 0
END AS itemD
FROM #table3
ORDER BY customerId, orderDate;
The desired result would look like:
CREATE TABLE desiredResult
(
customerId INT,
orderYear INT,
itemA INT,
itemB INT,
itemC INT,
itemD INT
);
INSERT INTO desiredResult (customerId, orderYear, itemA, itemB, itemC, itemD)
VALUES
('1', '2007', '1', '0', '1', '0'),
('1', '2009', '0', '0', '0', '1'),
('2', '2008', '0', '1', '1', '0'),
('3', '2009', '1', '0', '0', '0');
Is there an easier way to get the result I want? Is this something that PIVOT might be useful for?
I would do this using conditional aggregation:
SELECT customerId, OrderYear,
MAX(CASE WHEN item = 'a' THEN 1 ELSE 0 END) as itemA,
MAX(CASE WHEN item = 'b' THEN 1 ELSE 0 END) as itemB,
MAX(CASE WHEN item = 'c' THEN 1 ELSE 0 END) as itemC,
MAX(CASE WHEN item = 'd' THEN 1 ELSE 0 END) as itemD
FROM ((SELECT customerId, year(OrderDate) as OrderYear, item FROM table1
) union all
(SELECT customerId, year(OrderDate) as OrderYear, item FROM table2
)
) t
GROUP BY customerId, orderYear;
This also eliminates the need for temporary tables.
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
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
)