Create a new table based on a query SQL Server - sql

I have a query
with x as
(select row_number() over(partition by FirstName order by Investment_DT desc) as rn, *
from [dbSuppHousing].[dbo].[tblABC])
select Login_Name
,r.Role_Name
,Investment_DT
,FirstName
,LastName
,Login_Name
,Investment_DT
,Investment_ID
from x join tblUsers t
on t.UserName = x.Login_Name
join tblUser_Roles ur on t.User_Id=ur.USER_ID
join tblRoles r on r.Role_Id=ur.Role_ID
where x.rn = 1
order by x.FirstName
I want to insert the result of this query into another table as is.
Typically I use a query like:
insert into tblABC2
select * from tblABC
But I'm not sure how to do this in this case which is a query which begins with with x as

with x as
(select row_number() over(partition by FirstName order by Investment_DT desc) as rn, *
from [dbSuppHousing].[dbo].[tblABC])
select Login_Name
,r.Role_Name
,Investment_DT
,FirstName
,LastName
,Login_Name
,Investment_DT
,Investment_ID
into #temptable
from x join tblUsers t
on t.UserName = x.Login_Name
join tblUser_Roles ur on t.User_Id=ur.USER_ID
join tblRoles r on r.Role_Id=ur.Role_ID
where x.rn = 1
-- order by x.FirstName
You can use into to insert into the table you need. Also note that you can't do an order by when doing this (which has been commented out).

with x as (...) insert into tbl select * from x
So, insert should be directly after all CTEs used in the query.

You simply need to put the insert statement between the common table expression (CTE) and your select statement:
with x as
(select row_number() over(partition by FirstName order by Investment_DT desc) as rn, *
from [dbSuppHousing].[dbo].[tblABC])
/*
place insert statement here
*/
select Login_Name
,r.Role_Name
,Investment_DT
,FirstName
,LastName
,Login_Name
,Investment_DT
,Investment_ID
from x join tblUsers t
on t.UserName = x.Login_Name
join tblUser_Roles ur on t.User_Id=ur.USER_ID
join tblRoles r on r.Role_Id=ur.Role_ID
where x.rn = 1
order by x.FirstName
If you are running this on SQL Server 2008+, you need to ensure that any statement previous to the CTE is terminated with a semicolon.

Related

I need to only select the minimum value of my query

I have a view created in SQL Server Management Studio that brings in certain data, I need to only select the rows with the minimum sequence. For example, in the screenshot see the job number "50773-4", I would only need to see the row with SEQ number 2. I've tried to Group by Min, but to no avail. Any help would be appreciated.
SELECT
TOP (100) PERCENT dbo.Job_Operation.Job,
MIN(dbo.Job_Operation.Sequence) AS SEQ,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department
FROM
dbo.Job_Operation
INNER JOIN dbo.Job ON dbo.Job_Operation.Job = dbo.Job.Job
INNER JOIN dbo.User_Values ON dbo.Job.User_Values = dbo.User_Values.User_Values
INNER JOIN dbo.Work_Center ON dbo.Job_Operation.Work_Center = dbo.Work_Center.Work_Center
GROUP BY
dbo.Job_Operation.Job,
dbo.User_Values.Numeric2,
dbo.Work_Center.UVText4,
dbo.Job.Status,
dbo.Job_Operation.Status,
dbo.User_Values.Decimal1,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department
HAVING
(dbo.Work_Center.UVText4 = 'Machining')
ORDER BY
dbo.User_Values.Decimal1 DESC,
SEQ
[enter image description here]
I would try the RANK() window function. Perhaps:
SELECT column1,
column2,
rank() OVER (PARTITION BY job ORDER BY seq) AS seq_by_job
Then use this as a nested statement, and filter on only the min rank (i.e. WHERE nested_statement.seq_by_job = 1)
here is one way :
SELECT
TOP (100) PERCENT Job,
Sequence AS SEQ,
Work_Center,
Department
FROM
( select dbo.Job_Operation.Job,
dbo.Job_Operation.Sequence,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department,
dbo.User_Values.Decimal1 ,
ROW_NUMBER() over (partition by dbo.Job_Operation.Job,
dbo.User_Values.Numeric2,
dbo.Work_Center.UVText4,
dbo.Job.Status,
dbo.Job_Operation.Status,
dbo.User_Values.Decimal1,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department
Order by dbo.Job_Operation.Sequence asc) rn
FROM
dbo.Job_Operation
INNER JOIN dbo.Job ON dbo.Job_Operation.Job = dbo.Job.Job
INNER JOIN dbo.User_Values ON dbo.Job.User_Values = dbo.User_Values.User_Values
INNER JOIN dbo.Work_Center ON dbo.Job_Operation.Work_Center = dbo.Work_Center.Work_Center
) tt
WHERE rn = 1
and UVText4 = 'Machining'
You can do:
with
q as (
SELECT
dbo.Job_Operation.Job,
MIN(dbo.Job_Operation.Sequence) AS SEQ,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department,
dbo.User_Values.Decimal1
FROM
dbo.Job_Operation
INNER JOIN dbo.Job ON dbo.Job_Operation.Job = dbo.Job.Job
INNER JOIN dbo.User_Values
ON dbo.Job.User_Values = dbo.User_Values.User_Values
INNER JOIN dbo.Work_Center
ON dbo.Job_Operation.Work_Center = dbo.Work_Center.Work_Center
GROUP BY
dbo.Job_Operation.Job,
dbo.User_Values.Numeric2,
dbo.Work_Center.UVText4,
dbo.Job.Status,
dbo.Job_Operation.Status,
dbo.User_Values.Decimal1,
dbo.Job_Operation.Work_Center,
dbo.Work_Center.Department
HAVING
(dbo.Work_Center.UVText4 = 'Machining')
),
r as (
select *,
row_number() over(partition by job order by seq) as rn
from q
)
select job, seq, work_center, department
from r
where rn = 1
order by Decimal1 DESC

What will be the query for this?

JOIN public.match m ON (s.stadium_id = m.stadium_id)
group
AS (
)
SELECT round_number
,stadium_name
,spectators
FROM (
SELECT round_number
,stadium_name
,spectators
,RANK() OVER (
PARTITION BY round_number ORDER BY spectators DESC
) AS rank1
FROM t1
) AS s1
WHERE rank1 = 1
<br>
Any smaller query than this?
I think you can just use window functions:
select ms.*
from (select m.round_number, s.stadium_name, m.no_spectators,
row_number() over (partition by m.round_number order by m.no_spectators desc) as seqnum
from public.stadium s join
public.match m
on s.stadium_id = m.stadium_id
) ms
where seqnum = 1
order by m.round_number;
I don't see why aggregation would be needed for the inner query.
You can use a subquery to get the max first
select m.round_number, s.stadium_name, MaxSpec
from public.stadium s
JOIN public.match m ON (s.stadium_id = m.stadium_id)
JOIN
(
select m.round_number, MAX(m.no_spectators) as MaxSpec
from public.stadium s
JOIN public.match m ON (s.stadium_id = m.stadium_id)
group by m.round_number
)a on m.no_spectators = a.MaxSpec
Just one more way to skin this cat. Throw your MAX(no_spectators) into a WHERE clause.
SELECT
m.round_number,
s.stadium_name,
m.no_spectators
FROM
PUBLIC.stadium s
JOIN
PUBLIC.match m
ON s.stadium_id = m.stadium_id
WHERE
m.no_spectators = (SELECT MAX(no_spectators) FROM PUBLIC.match);
That should do for an intro class.

Get the latest value for each couple (name,address)

I have the following table for which I need to get the latest values for the group ( name , address ).
This means I need to have the max(time) for each ( name, address ) couple and get the last_read for that time value.
How can I do that in one select query ?
I think below should work for you, you need to use GROUP BY and MAX
select max([time]),
[name],
[address]
from yourTable
group by [name],
[address]
EDIT
You can try other answers or check below, which uses temp table
select max([time]) as last_read_time,
[name],
[address]
into #temp_table
from yourTable
group by [name],
[address]
select last_read
from yourTable as yt
inner join #temp_table t
on yt.[name] = t.[name]
and yt.[time] = t.last_read_time
IF OBJECT_ID('tempdb..#temp_table', 'U') IS NOT NULL
In most databases, a correlated subquery is a good approach:
select t.*
from t
where t.time = (select max(t2.time)
from t t2
where t2.name = t.name and t2.address = t.address
);
In particular, this can take advantage of an index on (name, address, time).
you can use row_number() if your dbms support
select * from
(select *,row_number() over(partition by name,address order by time desc) rn
) t where t.rn=1
None of the above solutions worked.
I finally found the following query that works :
select
l2.MAX t,
l.name,
l.address,
l.last_read
from links_data l
inner join (select name,
address,
max(time) as "MAX"
from links_data
group by name, address) l2
on l.name = l2.name
and l.address = l2.address
and l.time = l2.MAX;
Thanks everyone.

Join two tables returning only one row from the second table

I have this query:
SELECT t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,
t_ticket.code, t_ticket.priority, t_actionTicket.addedDateAction, t_actionTicket.title
FROM t_actionTicket INNER JOIN
t_ticket ON t_actionTicket.ticketID_FK = t_ticket.ticketID INNER JOIN
(SELECT ticketID_FK, MAX(addedDateAction) AS maxDate
FROM t_actionTicket AS t_actionTicket_1
WHERE (t_actionTicket.userID_FK <> #userid)
GROUP BY ticketID_FK) AS b ON t_actionTicket.ticketID_FK = b.ticketID_FK AND t_actionTicket.addedDateAction = b.maxDate
WHERE (t_ticket.supporterID_FK IN
(SELECT supporterID
FROM t_Supporter
WHERE (userID_FK = #userid)))
I want to return just the latest record in t_actionTicket table for each row in t_ticket table that t_actionTicket.userID_FK <> #userid.
but I have this error:
The multi-part identifier "t_actionTicket.userID_FK" could not be
bound.
Problem in your query is
FROM t_actionTicket AS t_actionTicket_1
WHERE t_actionTicket.userID_FK <> #userid -- here
You cannot use t_actionTicket alias name inside inner join select query. You need to use t_actionTicket_1. It is possible only in sub-query
Try this better way of doing it
;WITH cte
AS (SELECT t_ticket.ticketID,
t_ticket.addedDate,
t_ticket.question,
t_ticket.code,
t_ticket.priority,
t_actionTicket.addedDateAction,
t_actionTicket.title,
Row_number()
OVER(
partition BY ticketID_FK
ORDER BY addedDateAction DESC) RN
FROM t_actionTicket
INNER JOIN t_ticket
ON t_actionTicket.ticketID_FK = t_ticket.ticketID
WHERE t_ticket.supporterID_FK IN (SELECT supporterID
FROM t_Supporter
WHERE userID_FK = #userid))
SELECT *
FROM cte
WHERE rn = 1
You can write this logic using row_number() instead of additional nested queries:
SELECT t.ticketID, t.addedDate, t.question, t.code, t.priority,
ta.addedDateAction, ta.title AS Expr1
FROM t_Ticket t INNER JOIN
(SELECT ta.*,
ROW_NUMBER() OVER (PARTITION BY ta.ticketID_FK ORDER BY ta.addedDateAction DESC) as seqnum
FROM t_actionTicket ta
) ta
ON t.ticketId = ta.ticketId_FK and ta.seqnum = 1
WHERE t.supporterID_FK IN (SELECT supporterID
FROM t_Supporter
WHERE userID_FK = #userid
);
Note that table aliases make the query easier to write and to read.
Try this query
SELECT t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,
t_ticket.code, t_ticket.priority, t_actionTicket.addedDateAction, t_actionTicket.title
FROM t_actionTicket
INNER JOIN t_ticket ON t_actionTicket.ticketID_FK = t_ticket.ticketID
INNER JOIN (SELECT ticketID_FK, MAX(addedDateAction) AS maxDate
FROM t_actionTicket AS t_actionTicket_1
WHERE (t_actionTicket_1.userID_FK <> #userid)
GROUP BY ticketID_FK) AS b ON t_actionTicket.ticketID_FK = b.ticketID_FK AND t_actionTicket.addedDateAction = b.maxDate
WHERE (t_ticket.supporterID_FK IN
(SELECT supporterID
FROM t_Supporter
WHERE (userID_FK = #userid)))

SQL error occurs while running same SQL of Access2003 in SQL Server2008

I have the following SQL which is written in Access 2003. Now, I have to develop the prj with SQL Server2008 and
occur error when running this SQL at SQL Server2008 because First() function of Access cannot recogize in SQL Server 2008.
At SQL Server 2008, I tried with TOP() function but I still cannot slove it. Please help me.
SELECT DISTINCTROW TableA.TCode,
TableA.DCode,
TableA.DepCode,
TableA.ShouhinCode,
First(TableB.TName) AS TNameFirstRecord,
First(TableC.LDepName) AS LDepNameFirstRecord,
First(TableD.ThingType) AS ThingTypeFirstRecord,
First(TableA.GoodsName) AS GoodsNameFirstRecord,
Sum(TableA.Amount) AS AmountData,
Sum(TableA.MoneyAmount) AS MoneyAmountData,
Sum(TableA.DetailedMoneyAmount) AS DetailedMoneyAmounData,
Sum(TableA.SummaryMoneyAmount) AS SummaryMoneyAmountData,
TableA.POSNo
FROM (
(TableA INNER JOIN TableC ON TableA.DCode = TableC.DCode)
INNER JOIN TableB ON TableA.TCode = TableB.TCode
)
INNER JOIN TableD ON TableA.DepCode = TableD.DepCode
GROUP BY TableA.TCode,
TableA.DCode,
TableA.DepCode,
TableA.ShouhinCode,
TableA.POSNo
ORDER BY TableA.TCode,
TableA.DCode,
TableA.DepCode,
TableA.ShouhinCode
I think you'll need to use a Windowing Function
You replace your tables with versions that have Row Number on them
SELECT TableA.TCode,
A.DCode,
A.DepCode,
A.ShouhinCode,
B.TName AS TNameFirstRecord,
C.LDepNamee AS LDepNameFirstRecord,
D.ThingType AS ThingTypeFirstRecord,
A.GoodsNameAS GoodsNameFirstRecord,
Sum(A.Amount) AS AmountData,
Sum(A.MoneyAmount) AS MoneyAmountData,
Sum(A.DetailedMoneyAmount) AS DetailedMoneyAmounData,
Sum(A.SummaryMoneyAmount) AS SummaryMoneyAmountData,
A.POSNo
FROM
INNER JOIN (select row_number() over (partition by object_id ORDER BY Name DESC) as RowNumber, * from TableA) A
INNER JOIN (select row_number() over (partition by object_id ORDER BY Name DESC) as RowNumber, * from TableC) C ON A.DCode = C.DCode
INNER JOIN (select row_number() over (partition by object_id ORDER BY Name DESC) as RowNumber, * from TableB) B ON A.TCode = B.TCode
INNER JOIN (select row_number() over (partition by object_id ORDER BY Name DESC) as RowNumber, * from TableD) D ON A.DepCode = D.DepCode
WHERE
A.RowNumber = 1 AND B.RowNumber = 1 AND C.RowNumber = 1 AND D.RowNumber = 1
GROUP BY A.TCode,
A.DCode,
A.DepCode,
A.ShouhinCode,
A.POSNo
ORDER BY A.TCode,
A.DCode,
A.DepCode,
A.ShouhinCode