I connect four tables, but if I do a GROUP BY with a propertie of the fourth table, I get different results. This is the Query:
There are basically two options:
JOIN back to original table using nested query.
SELECT TA.col1, AggrFunc(col2) AS col2,
(SELECT col3 -- TOP 1? MAX? It must be single row
FROM table1 AS TB
JOIN TA ON TA. = TB. -- INNER JOIN? LEFT OUTER JOIN?
FROM table1 AS TB JOIN table2 JOIN table3
GROUP BY TA.col1;
Or use a CTE. You have more control on how many rows of extra columns to return
WITH CTE AS
(
SELECT col1, AggrFunc(col2) AS col2
FROM ... JOINs
GROUP BY col1
)
SELECT CTE.*, table1.col3
FROM CTE
JOIN table1 --INNER JOIN? LEFT OUTER JOIN?
Use window function if possible
SELECT col1, AggrFunc(col2) OVER (PARTITION BY col1) AS col2, extra_col3
FROM ...JOINs...
then you can put above query a CTE or FROM clause to further filtering or grouping.
SELECT
FROM (query above)
WHERE ...
GROUP BY ...
The question is same: How do you get single extra_col3(SKU.[Reorder Cycle] in your case) row? How do you pick up one record when there are multiple matches to your grouped data.
Oke, this was doing the job(oke, I made a pivot of it):
Related
I have a query which uses IN clause (can use EXISTS also) for multiple columns which are filtered using OR Clause inside WHERE Clause. Is there any better approach to write this query.
SELECT columndata FROM TABLE1
WHERE column1key in (select columnkey from #temptable1)
OR column2key in (select columnkey from #temptable2)
OR column3key IN (SELECT columnkey FROM #temptable3)
You can go for 'LEFT JOIN' as shown below
SELECT columndata
FROM TABLE1 tab1
LEFT JOIN #temptable1 t1 on tab1.column1key = t1.columnkey
LEFT JOIN #temptable2 t2 on tab1.column2key = t2.columnkey
LEFT JOIN #temptable3 t3 on tab1.column3key = t3.columnkey
You may get better performance by this, which breaks down the SELECT into separate queries with a de-duplication later.
SELECT columndata FROM TABLE1
WHERE column1key in (select columnkey from #temptable1)
UNION
SELECT columndata FROM TABLE1
WHERE column2key in (select columnkey from #temptable2)
UNION
SELECT columndata FROM TABLE1
WHERE column3key IN (SELECT columnkey FROM #temptable3)
But you would really have to try it
With no or bad indexes, you still have to scan then same amount of data. With good indexes, this may work better...
As a side note, EXISTS and IN will give the same plan here
while creating view I am getting error Column names in each view or function must be unique but while framing select query i am getting only one record.i have to use col1 and col2 for both the tables..if data doesnot exist in A table it will take from B table.how i can do this.Thanks in advance..
Create View ViewName AS
select
A.col1 as col1,
A.col2 as col2,
null as col1,
B.col2 as col2
from table A,table B where A.col3=B.col3
From your comments, it looks like you are looking for this:
Create View ViewName AS
select
A.col1,
COALESCE(A.col2, B.col2) AS col2
from table A
left join table B
on A.col3=B.col3;
Use a LEFT OUTER JOIN to handle the condition where the join fails.
Explanation of the actual error:
The error says it all - your view has two columns named col1 and two columns col2. Change the columns names of one of the sets. Unlike views, an adhoc select query doesn't require unique names (or any column name at all, for that matter).
Based on your comment, you will probably need something like this:
CREATE VIEW ViewName AS
SELECT ISNULL(A.col1, B.col1) as col1, -- This will return B.Col1 if A.Col1 is null
ISNULL(A.col2, B.col2) as col2,
FROM table A INNER JOIN table B ON(A.col3 = B.col3)
Edit
Based on your comments to this answer, you can do something like this:
ALTER VIEW temp AS
SELECT COALESCE(A.col1, D.col1) as col1,
COALESCE(A.col2, B.col2, C.col2, D.col2) as col2
FROM table A
INNER JOIN table1 B ON (A.col3=B.col3)
INNER JOIN table3 C ON (A.col3=C.col3)
INNER JOIN table4 D ON (A.col3=D.col3)
Note: you wrote COALESCE(A.col1,null,null,D.col1), this is equivalent to COALESCE(A.col1, D.col1), since the coalesce function will return the first argument it receives that is not null.
LIke this we can do?
alter view temp as select COALESCE(A.col1,null,null,D.col1) as col1, COALESCE(A.col2,B.col2,C.col2,D.col2) as col2 from table A INNER JOIN table1 B INNER JOIN table3 C INNER JOIN table4 ON (A.col3=B.col3 and A.col3=C.col3 and A.col3=D.col3)
Suppose you have two tables in a SQL Server database with the same schema for both tables. I want to compare a single column on both tables and find the values that are missing in table1 but are in table2. I've been doing this manually in Excel with a macro after I've gotten a distinct list in each query, but it would be less work if I had a query. How can I find the missing records via T-SQL? I'd like to do this for the following data types: datetime, nvarchar & bigint.
SELECT DISTINCT [dbo].[table1].[column1]
FROM [dbo].[table1]
ORDER BY [dbo].[table1].[column1] DESC
SELECT DISTINCT [dbo].[table2].[column1]
FROM [dbo].[table2]
ORDER BY [dbo].[table2].[column1] DESC
There are several ways you can do this...
LEFT JOIN:
SELECT DISTINCT t2.column1
FROM dbo.table2 t2
LEFT JOIN dbo.table1 t1
ON t2.Column1 = t1.Column1
WHERE t1.Column1 IS NULL
NOT EXISTS:
SELECT DISTINCT t2.column1
FROM dbo.table2 t2
WHERE NOT EXISTS (
SELECT 1
FROM dbo.table1 t1
WHERE t1.column1 = t2.column1
)
NOT IN:
SELECT DISTINCT t2.column1
FROM dbo.table2 t2
WHERE t2.column1 NOT IN (
SELECT t1.column1
FROM dbo.table1 t1
)
There are some slight variations in the behavior and efficiency of these approaches... based mostly on the presence of NULL values in columns, so try each approach to find the most efficient one that gives the results you expect.
SELECT DISTINCT [dbo].[table2].[column1]
FROM [dbo].[table2]
except
SELECT DISTINCT [dbo].[table1].[column1]
FROM [dbo].[table1]
All the values of column1 in Table2 that are not present in column1 of Table1
basically, you can use LEFT JOIN.
TableB is set as the main table in this case. By joining it with TableA using LEFT JOIN, the the records that have no match on TableA a will still be in the result list but their values are NULL. So to filter out non matching records, add a filtering condition which only select records with NULL value on tableA.
SELECT b.*
FROM tableB b
LEFT JOIN tableA a
ON a.column1 = b.column1
WHERE a.column1 IS NULL
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
SQL Server 2005 onwards you could use Except
SELECT DISTINCT [dbo].[table2].[column1]
FROM [dbo].[table2]
Except
SELECT DISTINCT [dbo].[table1].[column1]
FROM [dbo].[table1]
My original data is in Table2. I created Table1 from scratch. I populated Column A like this:
INSERT INTO Table1("item")
SELECT DISTINCT(Table2."item")
FROM Table2
I populated Table1.Totals (Column B) like this:
UPDATE Table1
SET totals = t2.q
FROM Table1 INNER JOIN
(
SELECT t2."item"
, SUM(t2.quantity) AS q
FROM t2
GROUP BY t2."item"
) AS t2
ON Table1."item" = t2."item"
How can I populate Table1."date"? My UPDATE above doesn't work here because I can't use an aggregate function on a date. I was able to get the results I wanted using the following code in a separate query:
SELECT DISTINCT Table1."item"
, Table2."date"
FROM Table1 INNER JOIN Table2
ON Table1."item" = Table2."item"
ORDER BY Table1."item"
But how do I use the results of this query to SET the value of the column? I'm using SQL Server 2008.
If you can't do the insert all over again, as #Lamak suggested, then you could perform an UPDATE this way:
UPDATE t1
SET t1.Date = s.Date
FROM Table1 AS t1
INNER JOIN
(
SELECT Item, [Date] = MAX([Date]) -- or MIN()
FROM Table2
GROUP BY Item
) AS s
ON t1.Item = s.Item;
For SQL Server you coul've use a single INSERT statement:
INSERT INTO Table1(Item, Totals, [Date])
SELECT Item, SUM(Quantity), MIN([Date]) -- It could be MAX([Date])
FROM Table2
GROUP BY Item
The easiest way is to use a simple CTAS (create table as select):
select item as item, SUM(quantity) as Q, MIN(date) as d into table2
from table1
group by item
Instead of creating a table, you could create a view, using a select statement like in #Lamak's answer. That way you wouldn't have to update the new row set each time the Table2 updates.
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