How to join a table to the result from a union query - sql-server

I am selecting data from 2 tables using union select:
select Product_Code from Discount_Table union select Product_Code from Discount2_Table
Union Query returns this
So after I select the data, I want to use this data to join on with other tables, example, Product_Table, but I'm having errors.
This is my query
select Product_Name, Price
from Discount_Table
union
select Product_Code
from Discount2_Table
join Product_Table on Discount_Table.Product_Code = Product_Table.Product_Code
Any tips/help would be appreciated!

You can use subquery like this:
SELECT * FROM
(select Product_Name,Price from Discount_Table union select Product_Code from Discount2_Table) Discount_Table
JOIN Product_Table ON Discount_Table.Product_Code = Product_Table.Product_Code

There are a few different ways you can refer to a results table later in a query, but here are a couple:
You can put the results from your first query into a CTE (Common Table Expression) and then join on that further down in your code:
WITH product_codes (Product_code) AS
(
select Product_Code
from Discount_Table
union
select Product_Code
from Discount2_Table
)
select t.Product_Name, t.Price
from product_codes pc
join Product_Table t on pc.Product_Code = t.Product_Code
You can also use temporary tables:
select Product_Code
INTO #product_codes
from Discount_Table
union
select Product_Code
from Discount2_Table
select t.Product_Name, t.Price
from #product_codes pc
join Product_Table t on pc.Product_Code = t.Product_Code
which works similarly by storing the results from your first query into a temporary table that you can access later on in the query. There are different reasons why you'd choose one version over the other, but they would both work enough to get you results.
I found a nice answer explaining the differences a bit more here.

Related

SQL Server query to get nested child records based on id provided by user

I have SQL Server data in the below format:
In the above table, parentid and sourceid are related, like the parent-child relationship.
in first-row parentid 'A' is sourceid of the second row. User will provide input of sourceid and based on that sourceid, I need to get its related child records.
For example, if the user provides input source id as 'A1', the output should be as shown below:
I tried using self join, but I am not able to get related child records in the table.
select *
from testrecords1 t1
join testrecords1 t2 on t1.parentid = t2.sourceid
where t1.sourceid = 'A1'
This query results in only one record. Please provide corrections / suggestions to achieve the desired output.
You can use Common Table Expression (CTE) for the recursive query.
The query could be written as:
;with MyCTE
as
(
SELECT Parentid, Sourceid from testrecords1 where SourceId = #SourceId
UNION ALL
SELECT t1.Parentid, t1.Sourceid from testrecords1 t1
inner join MyCTE t2 on t1.SourceId = t2.Parentid
)
SELECT * FROM MyCTE
Where #SourceId is the parameter for filter.

Check constraints not working on a query/view with join

We have a view described as the following :
CREATE view [dbo].[PriceHourlyView]
AS
select NodeId, TimeStamp,RtDa,MarketId,Lmp,Mlc,Mcc,Issettledprice,datecreated,IsCalculated from dbo.PriceHourly WITH (NOLOCK)
union all
select NodeId, TimeStamp,RtDa,MarketId,Lmp,Mlc,Mcc,Issettledprice,datecreated,IsCalculated from dbo.PriceHourly2018 WITH (NOLOCK)
union all
select NodeId, TimeStamp,RtDa,MarketId,Lmp,Mlc,Mcc,Issettledprice,datecreated,IsCalculated from dbo.PriceHourly2017 WITH (NOLOCK)
union all
select NodeId, TimeStamp,RtDa,MarketId,Lmp,Mlc,Mcc,Issettledprice,datecreated,IsCalculated from dbo.PriceHourly2016 WITH (NOLOCK)
union all
select NodeId, TimeStamp,RtDa,MarketId,Lmp,Mlc,Mcc,Issettledprice,datecreated,IsCalculated from dbo.PriceHourly2015 WITH (NOLOCK)
union all
select NodeId, TimeStamp,RtDa,MarketId,Lmp,Mlc,Mcc,Issettledprice,datecreated,IsCalculated from dbo.PriceHourly2014 WITH (NOLOCK)
union all
select NodeId, TimeStamp,RtDa,MarketId,Lmp,Mlc,Mcc,Issettledprice,datecreated,IsCalculated from dbo.PriceHourly2013 WITH (NOLOCK)
union all
select NodeId, TimeStamp,RtDa,MarketId,Lmp,Mlc,Mcc,Issettledprice,datecreated,IsCalculated from dbo.PriceHourly2012 WITH (NOLOCK)
Each of the tables has a check constraint as follows for each year except for the current table without year specified :
ALTER TABLE [dbo].[PriceHourly2017] WITH CHECK ADD CONSTRAINT [CK_PriceHourly2017_Timestamp] CHECK (([timestamp]>='2017-01-01' AND [timestamp]<='2017-12-31 23:59'))
When this view is queried by itself the check constraints limit the tables being searched. The execution plan looks like this :
SELECT
*
FROM PriceHourlyview
WHERE nodeid = 24511
AND TimeStamp BETWEEN '2017-05-17' AND '2017-05-24'
Now when I join on this table on the timestamp field the query no longer uses the check constraints and uses every table to check for the data.
SELECT
*
FROM ShapeProfileDetails s WITH (NOLOCK)
LEFT JOIN PriceHourlyView p WITH (NOLOCK)
ON s.TimeStamp = p.Timestamp
AND s.EffectiveDate BETWEEN '2017-05-17' AND '2017-05-24'
WHERE NodeId = 24512
--AND s.EffectiveDate BETWEEN '2017-05-17' AND '2017-05-24'
I know I'm not querying the same field in the joined example and assuming that's the issue but that is the field I need to query for the correct results. I'm wondering if there is anyway to hint or force the query to use the correct check constraints. Or what is the best practice on joining to try and utilize these check constraints.
Okay, as discussed we know that EffectiveDate and TimeStamp are nearly the same. I would try to do something like this. Technically it's the same query, but we will let know SQL Server that it can use constraints (just subtract and add one day on the edges of BETWEEN).
SELECT * FROM ShapeProfileDetails s WITH (NOLOCK)
JOIN PriceHourlyView p WITH (NOLOCK)
ON s.TimeStamp = p.Timestamp
AND s.EffectiveDate BETWEEN '2017-05-17' AND '2017-05-24'
AND s.TimeStamp BETWEEN '2017-05-16' AND '2017-05-25'
WHERE NodeId = 24512

Alternative of UNION in sql server

I have 2 tables which contains 5 unique cities each. I want all 10 cities but i don't want to use UNION. Is there any alternative for UNION.
SELECT DISTINCT CITY FROM TABLE1
UNION
SELECT DISTINCT CITY FROM TABLE2
Here is an alternate way
SELECT DISTINCT CASE WHEN a.city is null then b.city else a.city end
FROM Table1 FULL JOIN Table2b ON 1 = 0
it offers no advantage over UNION - but you might be interested in seeing FULL JOIN, which has its similarities to UNION
You can apply Full Outer join instead of Union
SELECT DISTINCT ISNULL(t.City,t1.City)
FROM dbo.TABLE1 t
FULL OUTER JOIN dbo.TABLE2 t1 ON t.City = t.City;
This query provides you the same result as union
You can insert the data that you want into a temporary table and retrieve it from there. That will avoid the need for a UNION.
SELECT DISTINCT CITY
INTO #City
FROM TABLE1
INSERT INTO #City
SELECT DISTINCT CITY
FROM TABLE2
SELECT DISTINCT City
FROM #City
If the first table is sure to contains all the records of the second table, then one can check if the id could be found inside a subquery with an OR clause.
I'm using an ORM framework which doesn't support the UNION operator (Apache OJB) and, with the above assumption, this strategy has proven to be faster than with the use of FULL OUTER JOIN.
For instance if the table STUDENT contains all the students of a province/state with a field for their current main school and another table, STUDENT_SECONDARY_SCHOOL, contains information for those students attending a second school part time, I can get the union of all students attending a particular school either full time or part time this way :
SELECT STD_ID FROM STUDENT
WHERE
STD_SCHOOL='the_school'
OR
STD_ID IN (SELECT STD_ID FROM STUDENT_SECONDARY_SCHOOL WHERE STD_SCHOOL='the_school')
Again, I want to emphasize that this is NOT the equivalent of a UNION but can be useful in some situations.

SQL queries combined into one row

I'm having some difficulty combining the following queries, so that the results display in one row rather than in multiple rows:
SELECT value FROM dbo.parameter WHERE name='xxxxx.name'
SELECT dbo.contest.name AS Event_Name
FROM contest
INNER JOIN open_box on open_box.contest_id = contest.id
GROUP BY dbo.contest.name
SELECT COUNT(*) FROM open_option AS total_people
SELECT SUM(scanned) AS TotalScanned,SUM(number) AS Totalnumber
FROM dbo.open_box
GROUP BY contest_id
SELECT COUNT(*) FROM open AS reff
WHERE refer = 'True'
I would like to display data from the fields in each column similar to what is shown in the image below. Any help is appreciated!
Tab's solution is fine, I just wanted to show an alternative way of doing this. The following statement uses subqueries to get the information in one row:
SELECT
[xxxx.name]=(SELECT value FROM dbo.parameter WHERE name='xxxxx.name'),
[Event Name]=(SELECT dbo.contest.name
FROM contest
INNER JOIN open_box on open_box.contest_id = contest.id
GROUP BY dbo.contest.name),
[Total People]=(SELECT COUNT(*) FROM open_option),
[Total Scanned]=(SELECT SUM(scanned)
FROM dbo.open_box
GROUP BY contest_id),
[Total Number]=(SELECT SUM(number)
FROM dbo.open_box
GROUP BY contest_id),
Ref=(SELECT COUNT(*) FROM open WHERE refer = 'True');
This requires the Total Scanned and Total Number to be queried seperately.
Update: if you then want to INSERT that into another table there are essentially two ways to do that.
Create the table directly from the SELECT statement:
SELECT
-- the fields from the first query
INTO
[database_name].[schema_name].[new_table_name]; -- creates table new_table_name
Insert into a table that already exists from the INSERT
INSERT INTO [database_name].[schema_name].[existing_table_name](
-- the fields in the existing_table_name
)
SELECT
-- the fields from the first query
Just CROSS JOIN the five queries as derived tables:
SELECT * FROM (
Query1
) AS q1
CROSS JOIN (
Query2
) AS q2
CROSS JOIN (...
Assuming that each of your individual queries only returns one row, then this CROSS JOIN should result in only one row.

Choose an aggregate function for Group BY in SQL Server

I have a query like this:
Select Count(*) as TotalCount, Object2_ID, Object_ID, Object_Description
from Table1
inner join table2 on...
Group BY Object2_ID, Object_ID
I can't run this query because the column Object_Description isn't in GROUP BY or under aggregate function. Object_Description is a text column. I need any value of Object_Description. Now I use MAX(Object_Description) because it gives me right results, because Object_Description is the same for each group.
I can use MAX() or MIN() etc. - I will get right results in my query.
The question is - what is the most sufficient way to do this ?
I think that MAX() or MIN() produces small overheads.
You can get Object Description later, after calculation quantity (assumed that description in in table1 and you need get count from Table2):
SELECT Object_Id, Object_Description, Qty
FROM
(
SELECT Object_Id, Count(*) Qty
FROM Table2
GROUP BY Object_Id
) t
JOIN Table1 t2 on t2.Object_Id = t.Object_Id

Resources