Get distinct result - sql

I have the following tables
Product --stored for productid
ProductRelation -- storing linked product id's
DECLARE #Product table(ProductID int)
DECLARE #ProductRelation TABLE (FirstProductID int,SecondProductID int)
INSERT INTO #Product
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION ALL
SELECT 6
UNION ALL
SELECT 7
UNION ALL
SELECT 8
UNION ALL
SELECT 9
UNION ALL
SELECT 10
--SELECT * FROM #Product
INSERT INTO #ProductRelation
SELECT 1,2
UNION ALL
SELECT 3,5
UNION ALL
SELECT 2,6
UNION ALL
SELECT 1,4
UNION ALL
SELECT 1,4
--SELECT * FROM #ProductRelation
SELECT ProductID,'Not Linked' AS 'Relation' FROM #Product
UNION
SELECT FirstProductID,'Linked' from #ProductRelation
UNION
SELECT SecondProductID ,'Linked' FROM #ProductRelation
Above query results repeating ProductID
I wanted to select distinct ProductID...if there is relation between product id then it should display the ProductID with 'Linked'
If no relation then ProductID with 'Not Linked'
I want the expected result like this
ProductID Relation
1 Linked
2 Linked
3 Linked
4 Linked
5 Linked
6 Linked
7 Not Linked
8 Not Linked
9 Not Linked
10 Not Linked

Try this:
SELECT
P.ProductID,
CASE WHEN COUNT(R.FirstProductID) > 0
THEN 'Linked'
ELSE 'Not Linked'
END Relation
FROM Product P
LEFT JOIN ProductRelation R
ON P.ProductID = R.FirstProductID
OR P.ProductID = R.SecondProductID
GROUP BY P.ProductID

well... I love this opportunity to use some unpivot tricks!
select P.ProductID
,isnull(L.relation,'Not Linked') as relation
from #Product P
left outer join (select U.ProductID, cast('Linked' as varchar(max)) as relation
from #ProductRelation
unpivot (ProductID for prod in (FirstProductID,SecondProductID))U
group by U.ProductID
)L
on L.ProductID = P.ProductID

You can use a left join combined with a CASE WHEN in SQL Server
SELECT DISTINCT
ProductID,
CASE WHEN #ProductRelation.FirstProductId IS NULL THEN 'Not Linked' ELSE 'Linked' END [Status]
FROM #Product
LEFT JOIN #ProductRelation ON #Product.ProductID = #ProductRelation.FirstProductId
RIGHT JOIN #ProductRelation ON #Product.ProductID = #ProductRelation.SecondProductId

Related

How to add a temp table in SQL server

I am trying to add a temp table to my query so that I can query that temp table, I have searched the internet but I couldn't get a solution.
this is my query
;WITH cte AS (
SELECT ID, g.Name
FROM game.Game g WITH(NOLOCK
WHERE ID IN (SELECT Data FROM system.Split(1, ','))
UNION ALL
SELECT g.ID, g.Name
FROM game.Game g WITH(NOLOCK)
JOIN cte ON g.ParentID = cte.ID
)
SELECT c.ID,
c.Name
FROM cte c
INNER JOIN list.Type gt WITH(NOLOCK) ON c.TypeId = gt.TypeID
WHERE c.ID NOT IN (SELECT Data FROM system.Split(1, ','))
AND c.ID IN (SELECT ID FROM game.code WITH(NOLOCK)
WHERE ID = c.ID
AND StatusCode IN ('OP', 'CL', 'SU')
AND isDisplay = 'True'
AND GETDATE() BETWEEN DisplayStart AND DisplayEnd
AND GETDATE() < ISNULL(ResultDateTime, ResultExpected)
)
which gives me the following when I run it
ID | Name
1111 | BaseBall
2222 |BasketBall
45896 |Relay
now I tried to create a temp table as follows
Create Table #temp(
ID int,
Name varchar
)
;WITH cte AS (
SELECT ID, g.Name
FROM game.Game g WITH(NOLOCK)
WHERE ID IN (SELECT Data FROM system.Split(1, ','))
UNION ALL
SELECT g.ID, g.Name
FROM game.Game g WITH(NOLOCK)
JOIN cte ON g.ParentID = cte.ID
)
insert into #temp // i wanted to set these values in the temp table
SELECT c.ID,
c.Name
FROM cte c
INNER JOIN list.Type gt WITH(NOLOCK) ON c.TypeId = gt.TypeID
WHERE c.ID NOT IN (SELECT Data FROM system.Split(1, ','))
AND c.ID IN (SELECT ID FROM game.code WITH(NOLOCK)
WHERE ID = c.ID
AND StatusCode IN ('OP', 'CL', 'SU')
AND isDisplay = 'True'
AND GETDATE() BETWEEN DisplayStart AND DisplayEnd
AND GETDATE() < ISNULL(ResultDateTime, ResultExpected)
)
every time I try to store this information in the temp table it gives me an error 'Column name or number of supplied values does not match table definition.' But I only have two values in. What am I doing wrong that I cant see?
First, why not just use select into?
IF OBJECT_ID('TempDB..#temp') IS NOT NULL
BEGIN
DROP TABLE #temp
END
select c.ID, c.Name
into #temp
from . . .
Then you don't need to define #temp as a table.
Next, your definition is bad, because Name has only one character. This would be fixed with select into.
However, I don't know why you are getting the particular error you are getting. The numbers of columns appears to match.

Querying a column that shows [count] of [max count]

I have 3 tables:
CustomerTypes table
Customers table (has a foreign key CustomerType). A customer can only have one customer type.
CustomersCollection table (contains many customerIds)
The primary SELECT of the query will be on CustomerTypes. I will be selecting two columns: CustomerTypeName and CountInCollection
The CustomerCount column in my query needs to show something like the following:
[Total # of Customers in CustomerType that are in Customer Collection] Of [Total # of Customers in CustomerType]
How can I get the proper customer count of the CustomerType that is part of the collection?
Example:
Customer1, Customer2, and Customer3 are all of CustomerTypeA.
CustomerCollection1 has customers Customer1 and Customer2 in it. The CountInCollection column for the CustomerTypeA record should show '2 of 3'.
Here is how I am able to get each count in separate queries:
-- Total customers in customer collection of customer type
SELECT COUNT(c.Id)
FROM Customer c
INNER JOIN CustomerCollection cc ON c.Id = cc.CustomerId
WHERE cc.CollectionId = 1019 AND c.CustomerTypeId=1000
-- Total customers in customer type
SELECT COUNT(Id) FROM
Customer WHERE CustomerTypeId=1000
Since you are using SQL 2008, I would take advantage of Common Table Expressions, aka CTEs, to assemble the data.
First, we'll need some test data. NOTE: I've thrown in some 'outliers' so that you can see where this kind of logic can bite you later.
DECLARE #CustomerTypes TABLE
(
CustomerTypeID INT,
[Customer Type] VARCHAR(100)
)
INSERT INTO #CustomerTypes
SELECT 1, 'TypeA'
UNION SELECT 2, 'TypeB'
UNION SELECT 3, 'TypeC' --NOTE: An outlier (not in customers-collection)
UNION SELECT 4, 'TypeD' --NOTE: An outlier (not in customers)
DECLARE #Customers TABLE
(
CustomerID INT,
CustomerTypeID INT
)
INSERT INTO #Customers
SELECT 1, 1
UNION SELECT 2, 1
UNION SELECT 3, 1
UNION SELECT 4, 2
UNION SELECT 5, 2
UNION SELECT 6, 2
UNION SELECT 7, 3
DECLARE #CustomersCollection TABLE
(
CollectionID INT IDENTITY(1,1),
CustomerID INT
)
INSERT INTO #CustomersCollection
(CustomerID)
SELECT TOP 2 --INSERT 2 of 3
CustomerID FROM #Customers WHERE CustomerTypeID = 1 --TypeA
INSERT INTO #CustomersCollection
(CustomerID)
SELECT TOP 1 --INSERT 1 of 3
CustomerID FROM #Customers WHERE CustomerTypeID = 2 --TypeB
Second, assemble the CTE data, and generate your output
;WITH CTE_COUNT_TYPE(CustomerTypeID, TypeCount)
AS
(
SELECT CustomerTypeID, COUNT(1)
FROM #Customers
GROUP BY CustomerTypeID
)
--SELECT * FROM CTE_COUNT_TYPE --DEBUG
,
CTE_COUNT_COLLECTION(CustomerTypeID, CollectionCount)
AS
(
SELECT CustomerTypeID, COUNT(1)
FROM #CustomersCollection CC
INNER JOIN #Customers C
ON CC.CustomerID = C.CustomerID
GROUP BY CustomerTypeID
)
--SELECT * FROM CTE_COUNT_COLLECTION --DEBUG
SELECT [Customer Type],
--CONVERT is necessary to combine INT data type (i.e. Count) and VARCHAR data type (i.e. 'as')
CONVERT(VARCHAR(100), COALESCE(CCC.CollectionCount, 0)) +
' of ' +
CONVERT(VARCHAR(100), COALESCE(CCT.TypeCount, 0)) As [Count in Collection]
FROM #CustomerTypes CT
LEFT OUTER JOIN #Customers C --Left outer join assists in outliers
ON CT.CustomerTypeID = C.CustomerTypeID
LEFT OUTER JOIN CTE_COUNT_TYPE CCT --Left outer join assists in outliers
ON CCT.CustomerTypeID = CT.CustomerTypeID
LEFT OUTER JOIN CTE_COUNT_COLLECTION CCC --Left outer join assists in outliers
ON CCC.CustomerTypeID = CT.CustomerTypeID
GROUP BY CT.[Customer Type]
, CCC.CollectionCount
, CCT.TypeCount
Hope so i get the question-
select
ct.CustomerTypeName as [Customer Type],
convert(varchar(30),count(cc.CollectionId)) + ' of ' + convert(varchar(30), count(c.CustomerId)) as [Count in Collection]
from
#Customer c
inner join #CustomerType ct on ct.CustomerTypeId = c.CustomerTypeId
left join #CustomerCollection cc on cc.CustomerId = c.CustomerId
group by
CustomerTypeName
Data script-
declare #customerType table (CustomerTypeId int, CustomerTypeName varchar(100))
insert into #customerType (CustomerTypeId, CustomerTypeName)
select 30, 'TypeA'
union
select 40, 'TypeB'
declare #customer table (CustomerId int, CustomerTypeId int)
insert into #customer (CustomerId, CustomerTypeId)
select 1, 30
union
select 2, 30
union
select 3, 30
union
select 4, 40
union
select 5, 40
union
select 6, 40
declare #customercollection table (CollectionId int, CustomerId int)
insert into #customercollection (CollectionId, CustomerId)
select 100, 1
union
select 200, 2
union
select 300, 5

Reusing part of already selected SQL query result - aka do not repeat itself

I have perfectly working SQL query:
SELECT
Product.ID
FROM
Product WITH (NOLOCK)
WHERE
Product.Type = 1 AND Product.No = '123456789'
UNION
SELECT
Description.ID
FROM
Description WITH (NOLOCK)
WHERE
Description.Opis LIKE '%hello%'
AND Description.ID IN (SELECT Product.ID
FROM Product WITH(NOLOCK)
WHERE Product.Type = 1)
but I am worried about repeating following
SELECT Product.ID
FROM Product WITH(NOLOCK)
WHERE Product.Type = 12
Is there a way to query for it once and reuse it in those 2 places?
Use a common table expression (cte):
with cte as (
SELECT Product.ID, Product.No
FROM Product WITH(NOLOCK)
WHERE Product.Type = 1
)
SELECT ID
FROM cte
WHERE No = '123456789'
UNION
SELECT Description.ID
FROM Description WITH(NOLOCK)
WHERE Description.Opis LIKE '%hello%'
AND Description.ID IN (SELECT ID from cte)
BTW, maybe you want UNION ALL instead of UNION? (Should duplicate rows be kept or removed?)
It is possible to also use table variables. Also added join in the second part of UNION:
DECLARE #ProductTemp TABLE (Id int, No int)
INSERT INTO #ProductTemp
SELECT Product.Id, Product.No
FROM Product WITH(NOLOCK)
WHERE Product.Type = 1
SELECT ID
FROM #ProductTemp
WHERE No = '123456789'
UNION
SELECT Description.ID
FROM Description WITH (NOLOCK)
INNER JOIN #ProductTemp AS p ON Description.ID = p.ID
WHERE Description.Opis LIKE '%hello%'

Order by 5 consecutive rows alternating between results

I'm trying to select from two categories, but I want to alternate between categories by grouping five of each categories.
Here are the tables
SELECT MC.main_category_id, MC.main_category_name, MC.order_by_num AS MC_Order,
C.category_id, C.category_name, C.order_by_num AS C_Order, C.gift, I.item_id, I.model_num, I.item_title, B.brand_name, I.price, I.suggested_price, i.description
FROM dbo.tblMainCategories AS MC
INNER JOIN dbo.tblCategories AS C ON MC.main_category_id = C.main_category_id
INNER JOIN dbo.tblItemCategories AS IC ON MC.main_category_id = IC.main_category_id
AND C.category_id = IC.category_id
INNER JOIN dbo.tblItems AS I ON IC.ic_item_id = I.item_id
INNER JOIN dbo.tblBrands AS B ON I.brand_id = B.brand_id
WHERE (MC.store_id = 14) AND (IC.store_id = 14) AND I.isActive = 1
And MC.main_category_id in (1,2)
ORDER BY MC.order_by_num, C.order_by_num, I.order_by_num,I.price
How can I sort this result that it should be ordered by 5 of MainCategory 1 then 5 of MainCategory 2 and then 5 of MainCategory 1 and continue 5 of each until the end.
MainCategory 1 has much more items than MainCategory 2. the rest of the MainCategory 1 should also be at the bottom.
You could try something like this. Just be sure your results are order the way you want when inserting them into the SQL tables. Break the query into 2 duplicates that insert the results into some temp tables. Then you can iterate through the results inserting each 5 into a third results table.
Here is an example of the approach I took with a db I had available to me.
create table #result(AccountID int, AccountTypeID int, AccountName varchar(128))
select AccountID, ab.AccountTypeID, AccountName INTO #Temp from AccountBase ab
join AccountType at on ab.AccountTypeId = at.AccountTypeId
where ab.AccountTypeId in (1)
order by AccountName
select AccountID, ab.AccountTypeID, AccountName INTO #Temp2 from AccountBase ab
join AccountType at on ab.AccountTypeId = at.AccountTypeId
where ab.AccountTypeId in (2)
order by AccountName
While ((select count(*) from #Temp) > 0 or (select count(*) from #Temp2) > 0)
begin
If (select count(*) from #Temp) > 0
Begin
insert into #result select Top(5) * from #Temp
delete top(5) from #Temp
End
If (select count(*) from #Temp2) > 0
Begin
insert into #result select Top(5) * from #Temp2
delete top(5) from #Temp2
End
End
select * from #result
drop table #Temp
drop table #Temp2
drop table #result
I believe everything is supported by SQL 2000.

Need help on SQL join

I have 2 tables as below:
select 1 as id,
'A' as place
into #places
UNION
select 2 as id,
'B' as place
UNION
select 3 as id,
'C' as place
UNION
select 4 as id,
'D' as place
select 'x' as name,
2 as start,
3 as endd
into #travel
UNION
select 'y' as name,
4 as start,
1 as endd
UNION
select 'z' as name,
1 as start,
3 as endd
select * from #places
select * from #travel
------------------------------
Now I want to get name/start place/end place using joins?
SELECT
t.name,
p1.place as start_place,
p2.place as end_place
FROM
travel t
JOIN places p1 on t.start = p1.id
JOIN places p2 on t.endd = p2.id
select #travel.*, pstart.place as start, pend.place as end
from #travel inner join #places as pstart on pstart.id = #travel.start
inner join #places as pend on pend.id = #travel.end