I have a table which contains data in this format.
ProductID ShipId
11 1
11 2
11 3
22 1
22 2
33 1
33 2
Now I want only the distinct product ids where ship id 3 is not associated.
Output should be
22,33 only.
I have used this query but it throws error.
Select distinct productid from X_product_ship group by productid having shipid <> 3
Please help.
Use a subquery in the where clause to exclude the products that has a shipid of three.
select distinct P1.ProductID
from dbo.X_product_ship as P1
where P1.ProductID not in (
select P2.ProductID
from dbo.X_product_ship as P2
where P2.ShipId = 3
)
SQL Fiddle
Or you could get creative in the having clause using a case statement.
select P.ProductID
from dbo.X_product_ship as P
group by P.ProductID
having max(case when P.ShipId = 3 then 1 else 0 end) = 0
SQL Fiddle
Related
I want this query to return 1 also in the case when no record exists. With a count less than 2 or even if no records exist it should return 1.
SELECT 1
FROM dbo.Product BS
WHERE BS.ASIN = '072142452X'
GROUP BY ASIN
HAVING COUNT(1) < 2
The result should be 1 in the case when no record exists in the table.
List of All Products In table
Product
Id ASIN
1 12A
2 12B
3 1AC
4 123
5 12D
List of Accounts
Account
Id Name
1 A
2 B
3 C
Now Listing happens in various accounts
List of products Listed in various accounts (Product Id and Account combination is unique. Means one product will be listed in one account only once)
ProductListing
Id ProductId AccountId
1 2 1
2 1 1
3 4 1
4 2 2
5 4 2
6 5 3
I want if a product is already listed in one account or in two different accounts it should not come in my query of listing product
Query of Listing product in Account 3. So products which are already listed in 3 and in more than 2 accounts should not come
Select P.Id, P.ASIN
FROM dbo.Product P
WHERE NOT EXISTS (
SELECT 1
FROM dbo.ProductListing PL
WHERE P.Id = PL.ProductId AND AccountId = 3
) AND EXISTS (
SELECT 1
FROM dbo.ProductListing PL
WHERE P.Id = PL.ProductId
GROUP BY PL.ProductId
HAVING COUNT(1) < 2
)
You can use a CASE expression on the number of rows returned as follows.
DECLARE #Asin varchar(10) = '072142452X';
SELECT
CASE WHEN (
SELECT COUNT(*)
FROM dbo.Product BS
WHERE BS.[ASIN] = #Asin
) < 2 THEN 1 ELSE 0 END;
Note: there is no reason to GROUP BY when you are already filtering down to 1 ASIN.
Based on your edit you can modify your query to use the same sub-query as I have already show as follows:
SELECT P.Id, P.[ASIN]
FROM dbo.Product P
WHERE NOT EXISTS (
SELECT 1
FROM dbo.ProductListing PL
WHERE PL.ProductId = P.Id AND AccountId = 3
) AND (
SELECT COUNT(*)
FROM dbo.ProductListing PL
WHERE PL.ProductId = P.Id
) < 2;
Drop your GROUP BY line.
Consider how this will always give a row:
SELECT COUNT(1)
FROM dbo.Product BS
WHERE BS.ASIN = '072142452X'
But GROUP BY means you return a row per group, and you don't have any groups because you're filtering out the rows that would've made one.
So this is what you want.
SELECT 1
FROM dbo.Product BS
WHERE BS.ASIN = '072142452X'
Having Count(1) < 2
ADDENDUM: I wrote it this way because it's the closest to the OP's original form. But another option, which doesn't get caught up in the nuances of GROUP BY and HAVING is:
SELECT 1
WHERE (
SELECT COUNT(1)
FROM dbo.Product BS
WHERE BS.[ASIN] = '072142452X'
) < 2
Table: ProductionOrder
Id Ordernumber Lotsize
1 Order1 50
2 Order 2 75
3 WO-order1 1
4 WO-order2 1
Table: history
Id ProductionOrderID Completed
1 3 1
2 3 1
3 4 1
4 4 1
Table: ProductionOrderDetail
ID ProductionOrderID ProductionOrderDetailDefID Content
1 1 16 50
2 1 17 7-1-2018
3 2 16 75
4 2 17 7-6-2018
Start of my code:
Select p.ID, p.OrderNumber,
Case productionOrderDetailDefID
Where(Select pd1.productionOrderDetailDefID where ProductionOrderDetialDefID = 16) then min(pd1.content)
from ProductionOrder p
Left join History h1 on p.id = h1.productionOrderID
Left Join ProductionOrderDetail pd1 on p.ID = ProductionOrderID
The result in trying to get is
Id Ordernumber Lotsize Productionorder Completed
1 Order1 50 WO-order1 2
2 Order 2 75 WO-order2 2
Any help would be appreciated.
Try this
SELECT ordernumber,lotsize,Ordernumber,count(Ordernumberid)
FROM productionorder inner join history on productionorder.id = history.Ordernumberid
GROUP BY Ordernumber;
A bit of weird joins going on here. You should add this to a SQL fiddle so that we can see our work easier.
A link to SQL fiddle: http://sqlfiddle.com/
Here is my first attempt
SELECT
po.id
, po.ordernumber
, po.lotsize
, po2.productionorder
, SUM(h.completed)
FROM productionorder as po
INNER JOIN history as h
ON h.id = po.id
INNER JOIN prodcuctionorder as po2
ON po2.ordernumberid = h.ordernumberid
WHERE po.id NOT EXISTS IN ( SELECT ordernumberid FROM history )
GROUP BY
po.id
, po.ordernumber
, po.lotzise
, po2.productionorder
How far does that get you?
I have two table Customer-items and Available-locations i need to get the location where all items in customer-items are available.
Customer-items
ItemID ItemName
1 item1
2 item2
3 item3
Available-locations
LocationID ItemID AvailableForPickup
20 1 1
20 2 1
20 3 0
21 1 1
21 2 1
21 3 1
on simple inner join e.g
SELECT * FROM Customer-items
INNER JOIN Available-locations
ON Customer-items.ItemID = Available-locations.ItemsID AND AvailableForPicup = 1
this will exclude item 3 from Available-locations for LocationID 20 but return other two items for locationID 20 and all items for location 21.
i need to get the result set like; to exclude all items for location if any of item is not available.
Available-locations_CustomerItems
LocationID ItemID AvailableForPickup
21 1 1
21 2 1
21 3 1
select * from Customer-items
join Available-locations
on Customer-items.ItemID = Available-locations.ItemsID
where Available-locations.LocationID in
(select LocationID from Available-locations where AvailableForPickup = 1)
Please use the below code. It's working fine with SQL Server 2012.
DECLARE #Customer_Items TABLE (ItemsID int,ItemName VARCHAR(10))
DECLARE #Available_Locations TABLE (LocationID int,ItemsID int,AvailableForPickup int)
INSERT INTO #Customer_Items (ItemsID,ItemName)
VALUES
(1,'item1'),
(2,'item2'),
(3,'item3')
INSERT #Available_Locations
(LocationID,ItemsID, AvailableForPickup)
VALUES
(20,1,1),
(20,2,1),
(20,3,0),
(21,1,1),
(21,2,1),
(21,3,1)
SELECT LocationID,al.ItemsID,AvailableForPickup FROM #Customer_Items ci
INNER JOIN #Available_Locations al
ON ci.ItemsID = al.ItemsID AND al.AvailableForPickup = 1
WHERE al.LocationID NOT IN (SELECT al2.LocationID FROM #Available_Locations al2 WHERE al2.AvailableForPickup =0)
You could use NOT IN in following:
SELECT l.*
FROM [Customer-items] AS i
INNER JOIN [Available-locations] AS l ON i.ItemID = l.ItemID
WHERE l.LocationID NOT IN (SELECT LocationID FROM [Available-locations] WHERE AvailableForPicup = 0)
Note that - is not available in tables names. You have to use brackets [] on table names like [customer-items]. Also use alias names on tables to make It more readable.
OUTPUT
LocationId ItemId AvailableForPickup
21 1 1
21 2 1
21 3 1
SELECT B.ITEMID
,B.LOCATIONID
,B.AVAILABLEFORPICKUP
FROM #A A
RIGHT JOIN #B B ON A.ITEMID = B.ITEMID
WHERE B.AVAILABLEFORPICKUP= 1
SELECT * FROM Customer-items
INNER JOIN Available-locations
ON Customer-items.ItemID = Available-locations.ItemsID AND locationId
NOT IN (select locationID FROM Available-locations WHERE AvailableForPicup = 0)
I have the following query,
SELECT * FROM Products P
OUTER APPLY
(
SELECT COALESCE(CP.NewPrice, CP.Price, 2147483647) AS MinimumChildPrice
--,SelectedMinimumPriceRow.Promotion
FROM Products CP
WHERE CP.ParentID = P.ID
) AS C
The problem is SelectedMinimumPriceRow.Promotion. I need to select this extra Promotion column of selected Minimum Price/NewPrice?
For example if I have,
ID ParentID Promotion Price NewPrice
----------------------------------------
1 NULL a 81 52
2 1 b 11 81
3 1 c 91 14
4 1 d 11 25
5 1 e 10 61
For ID=1, the minimum price will be 14. So, I need to select c as well.
You could simply replace your OUTER APPLY query with a TOP 1 query ordering by price, that will allow you to grab any column;
SELECT * FROM Products P
OUTER APPLY
(
SELECT TOP 1 COALESCE(CP.NewPrice, CP.Price, 2147483647) MinimumChildPrice,
promotion MinimumChildPricePromotion
FROM Products CP
WHERE CP.ParentID = P.ID
ORDER BY COALESCE(CP.NewPrice, CP.Price, 2147483647)
) AS C
An SQLfiddle to test with.
i have 3 tables Product Category and ProductCategory.
Product table:
ProductID ProductName
1 P1
2 P2
3 P3
Category table:
CategoryID CategoryName
1 C1
2 C2
3 C3
ProductCategory:
ProductID CategoryID
1 1
1 2
1 3
2 3
3 1
3 2
I need a query which returns products which fall under more than 1 categories. Based on the table data above the result would be:
ProductID ProductName
1 P1
3 P3
So i wrote a query to fetch all the ProductID's which have more than one CategoryID's as below:
select ProductID,count(CategoryID)
from ProductCategory
group by Productid
having count(CategoryID)>1)
But when i try to display product details using the below query i get an error:
select *
from Product
where ProductID in (
select ProductID,count(CategoryID)
from ProductCategory
group by Productid
having count(CategoryID)>1))
Is my query wrong? How do i get the required product details which fall in more than one categories?
Remove the COUNT() in the subquery. The result of the subquery when used on IN clause must have only one returned column.
SELECT *
FROM Product
WHERE ProductID IN
(
SELECT ProductID
FROM ProductCategory
GROUP BY Productid
HAVING count(CategoryID) > 1
)
SQLFiddle Demo
or by using JOIN
SELECT a.*
FROM Product a
INNER JOIN
(
SELECT ProductID
FROM ProductCategory
GROUP BY Productid
HAVING count(CategoryID) > 1
) b ON a.ProductID = b.ProductID
SQLFiddle Demo
You can try use CROSS APPLY Operator in SQL Server
SELECT DISTINCT C.ProductID,C.ProductName,A.CategoryID,A.Total
FROM Product C
CROSS APPLY (
Select CA.CategoryID,Total=COUNT(*)
From ProductCategory CA
Where C.ProductID=CA.ProductID
Group By CA.CategoryID Having COUNT(*)>1
) AS A
ORDER BY A.Total DESC
Take a look: http://explainextended.com/2009/07/16/inner-join-vs-cross-apply/