Updating column with value from other table, can't use distinct function - sql-server

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.

Related

How to do a looping select union in Postgres

I'm trying to do select from Table2 for each row in an initial select statement from Table1.
Initial select statement would look something like
Select * from Table1 Where GroupID='someId' AND ObjectID='someID'
Table1 would return something like the following (there will only ever be 0-1 returned rows with a null EndDate value).
Table2 will look as follows
Basically my goal is to loop through the first select statements rows. For each row I want to take the objectid, startdate, and enddate to select all the appropriate rows in Table2. Then after do a UNION(?) on all the data I've selected from Table2. I want to be able to select all the rows in Table2 which's objectid matches the objectid given and the timestamp is in-between the start/end dates (or to current timestamp if enddate is null). Does that make sense? I've been looking online, but have not found a way to achieve a looping select union like this.
I'm not sure if this is possible in a single select statement or if a stored proc is needed/cleaner (either is fine but I'd rather avoid stored proc if I can).
You can do it with a join:
SELECT t2.*
FROM Table2 t2 INNER JOIN Table1 t1
ON t1.objectid = t2.objectid
AND t2.timestamp BETWEEN t1.startdate AND COALESCE(t1.enddate, current_timestamp)
WHERE t1.GroupID = 'someId' AND t1.ObjectID = 'someID'

Keeping the results with GROUP BY

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):

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.

Find missing values on the same column of two tables

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]

SQL Server - Invalid object name while joining table to itself

I've tried to find an answer to my problem but couldn't find similar example.
I have results from such a query
SELECT * FROM (
SELECT id FROM table
) AS t1
Now I would like to join t1 to another instance of itself because I need to shift it. For example if I wanted to compare a row with the previous one. I tried:
SELECT * FROM (
SELECT id FROM table
) AS t1
LEFT JOIN t1 AS t2 ON (my conditions)
But I get an error that t1 is invalid object name. When I copy my select statement:
SELECT * FROM (
SELECT id FROM table
) AS t1
LEFT JOIN (
SELECT id FROM table
) AS t2 ON (my conditions)
The above works, but is it not slower than joining to already returned results?
Any help would be appreciated
The first one is in correct:
SELECT * FROM (
SELECT id FROM table
) AS t1
LEFT JOIN t1 AS t2 ON (my conditions)
Because you can't alias an alias. You can do something similar to it using CTE like so:
;WITH cte
AS
(
SELECT * FROM Table
)
SELECT *
FROM Cte t1
INNER JOIN cte t2 ON --
I think your select should be of the form:
SELECT *
FROM [table] t1
LEFT JOIN [table] t2 ON (your conditions)
From a performance perspective, this is identical to your last select and to the CTE solution in Mahmoud's answer (I've reviewed the execution plan for all three in SQL Server).
It might only be a matter of taste, but I find this form to be more readable/maintainable.

Resources