Putting the results of a query into new table in SQL Server - sql

I want to insert query results into new table is there any way I can make changes in code so that it gets stored in a table.
My query:
SELECT DISTINCT TOP 5 a.DocEntry
,b.TrgetEntry
,b.itemcode
,a.DocNum AS 'Order No.'
,a.CardCode
,a.CardName
,b.DocDate AS [Delivery No.]
,c.targettype AS 'Ctargettype'
,c.trgetentry AS 'Ctargetentry'
,c.itemcode AS 'c-itemcode'
,c.docentry AS 'Cdocentry' a.CancelDate
,a.Project
,a.DocStatus
,b.ObjType
,a.ObjType
FROM ORDR a
INNER JOIN rdr1 b ON a.DocEntry = b.DocEntry
LEFT JOIN dln1 c ON c.TrgetEntry = b.DocEntry
AND b.itemcode = c.ItemCode order by c.itemcode;

You can do it as it will create a new table and insert the records into that table. If you have already created table then you can give name and individual columns also for both insertion and selection.
SELECT *
INTO YourTableName
FROM (
SELECT DISTINCT TOP 5 a.DocEntry
,b.TrgetEntry
,b.itemcode
,a.DocNum AS 'Order No.'
,a.CardCode
,a.CardName
,b.DocDate AS [Delivery No.]
,c.targettype AS 'Ctargettype'
,c.trgetentry AS 'Ctargetentry'
,c.itemcode AS 'c-itemcode'
,c.docentry AS 'Cdocentry' a.CancelDate
,a.Project
,a.DocStatus
,b.ObjType
,a.ObjType
FROM ORDR a
INNER JOIN rdr1 b ON a.DocEntry = b.DocEntry
LEFT JOIN dln1 c ON c.TrgetEntry = b.DocEntry
AND b.itemcode = c.ItemCode
)
a
For using order by clause you can try something like this.
SELECT DISTINCT
Insured_Customers.FirstName, Insured_Customers.LastName,
Insured_Customers.YearlyIncome, Insured_Customers.MaritalStatus
INTO Fast_Customers from Insured_Customers INNER JOIN
(
SELECT * FROM CarSensor_Data where Speed > 35
) AS SensorD
ON Insured_Customers.CustomerKey = SensorD.CustomerKey
ORDER BY YearlyIncome;
You can learn in detail about INTO Clause Here

This looks like SQL Server code. In that database, you add into after the select clause:
Select distinct top 5 o.DocEntry, r.TrgetEntry, r.itemcode, o.DocNum as order_num, o.CardCode,
o.CardName, r.DocDate as delivery_num,
d.targettype as Ctargettype, d.trgetentry as Ctargetentry,
d.itemcode as c_itemcode, d.docentry as Cdocentry
a.CancelDate,a.Project, a.DocStatus,b.ObjType,a.ObjType
into <new table>
from ORDR o inner join
rdr1 r
On o.DocEntry = r.DocEntry left join
dln1 d
on d.TrgetEntry = r.DocEntry and
d.itemcode = r.ItemCode;
Note that I changed the table aliases so they are meaningful. Arbitrary letters are very hard to follow. Table abbreviations are more useful.
I also changed the column aliases so they do not need to be escaped. Do not make troublesome aliases!

Related

Optimising SQL Query with multiple joins, reducing query speed

I'd like some advice on how to optimize the code below. I have attached the relationship of table above, any feedback or direction you could point me to will be appreciated.
The current query seems to be taking quite long to process.
SELECT CUSTINVOICETRANS.INVENTTRANSID, CUSTINVOICETRANS.INVOICEDATE, CUSTINVOICETRANS.INVOICEID, CUSTINVOICETRANS.ITEMID, CUSTINVOICETRANS.LINEAMOUNT, CUSTINVOICETRANS.LINEAMOUNTTAX, CUSTINVOICETRANS.ORIGSALESID, CUSTINVOICETRANS.QTY, CUSTINVOICETRANS.SUMLINEDISC, CUSTINVOICEJOUR.CUSTGROUP, CUSTINVOICEJOUR.INVOICEACCOUNT, CUSTINVOICEJOUR.SALESID, SALESTABLE.VCORDERMODE, SALESTABLE.VCORDERRT, VCSALESTABLEINFO.RCVDATE, VCSALESTABLEINFO.SHPCSTMCD, VCSALESTABLEINFO.VCORIGINALINVOICEDATE, SALESLINE.DATAAREADID, SALESLINE.INVENTTRANSID, VCSALESLINEINFO.RLLINEID
FROM CUSTINVOICETRANS
INNER JOIN CUSTINVOICEJOUR
ON CUSTINVOICETRANS.INVOICEID = CUSTINVOICEJOUR.INVOICEID
AND CUSTINVOICETRANS.INVOICEDATE = CUSTINVOICEJOUR.INVOICEDATE
AND CUSTINVOICETRANS.INVOICEDATE>=DATEADD(DAY,-7,GETDATE())
INNER JOIN SALESTABLE
ON CUSTINVOICETRANS.ORIGSALESID = SALESTABLE.SALESID
AND CUSTINVOICETRANS.INVOICEDATE>=DATEADD(DAY,-7,GETDATE())
INNER JOIN VCSALESTABLEINFO
ON CUSTINVOICETRANS.ORIGSALESID = VCSALESTABLEINFO.SALESID
AND CUSTINVOICETRANS.INVOICEDATE>=DATEADD(DAY,-7,GETDATE())
INNER JOIN SALESLINE
ON CUSTINVOICETRANS.ORIGSALESID = SALESLINE.SALESID
AND CUSTINVOICETRANS.INVOICEDATE>=DATEADD(DAY,-7,GETDATE())
INNER JOIN VCSALESLINEINFO
ON SALESLINE.INVENTTRANSID = VCSALESLINEINFO.INVENTTRANSID```
You can use cte to filter first your customer invoice transactions before joining other tables.
WITH cte as
(
SELECT INVENTTRANSID, INVOICEDATE, INVOICEID
, ITEMID, LINEAMOUNT, LINEAMOUNTTAX
, ORIGSALESID, QTY, SUMLINEDISC
FROM CUSTINVOICETRANS WHERE INVOICEDATE>=DATEADD(DAY,-7,GETDATE())
)
SELECT t1.*, t2.CUSTGROUP, t2.INVOICEACCOUNT, t2.SALESID
, t3.VCORDERMODE, t3.VCORDERRT
, t4.RCVDATE, t4.SHPCSTMCD, t4.VCORIGINALINVOICEDATE
, t5.DATAAREADID, t5.INVENTTRANSID
, t6.RLLINEID
FROM cte t1
INNER JOIN CUSTINVOICEJOUR t2 on t2.INVOICEID = t1.INVOICEID and t1.INVOICEDATE = t2.INVOICEDATE
INNER JOIN SALESTABLE t3 on t3.SALESID = t1.ORIGSALESID
INNER JOIN VCSALESTABLEINFO t4 on t4.SALESID = t1.ORIGSALESID
INNER JOIN SALESLINE t5 on t5.SALESID = t1.ORIGSALESID
INNER JOIN VCSALESLINEINFO t6 on t6.INVENTTRANSID = t5.INVENTTRANSID
Pull the first INNER JOIN outcome to a dataframe / temp table t1.
Join the same with second INNER Join dataset.
pull the data into another temp table / data frame.
Drop the temp table t1 at the end.
Follow the step for for subsequesnt joins.
Regards

How to create distinct count from queries with several tables

I am trying to create one single query that will give me a distinct count for both the ActivityID and the CommentID. My query in MS Access looks like this:
SELECT
tbl_Category.Category, Count(tbl_Activity.ActivityID) AS CountOfActivityID,
Count(tbl_Comments.CommentID) AS CountOfCommentID
FROM tbl_Category LEFT JOIN
(tbl_Activity LEFT JOIN tbl_Comments ON
tbl_Activity.ActivityID = tbl_Comments.ActivityID) ON
tbl_Category.CategoryID = tbl_Activity.CategoryID
WHERE
(((tbl_Activity.UnitID)=5) AND ((tbl_Comments.PeriodID)=1))
GROUP BY
tbl_Category.Category;
I know the answer must somehow include SELECT DISTINCT but am not able to get it to work. Do I need to create multiple subqueries?
This is really painful in MS Access. I think the following does what you want to do:
SELECT ac.Category, ac.num_activities, aco.num_comments
FROM (SELECT ca.category, COUNT(*) as num_activities
FROM (SELECT DISTINCT c.Category, a.ActivityID
FROM (tbl_Category as c INNER JOIN
tbl_Activity as a
ON c.CategoryID = a.CategoryID
) INNER JOIN
tbl_Comments as co
ON a.ActivityID = co.ActivityID
WHERE a.UnitID = 5 AND co.PeriodID = 1
) as caa
GROUP BY ca.category
) as ca LEFT JOIN
(SELECT c.Category, COUNT(*) as num_comments
FROM (SELECT DISTINCT c.Category, co.CommentId
FROM (tbl_Category as c INNER JOIN
tbl_Activity as a
ON c.CategoryID = a.CategoryID
) INNER JOIN
tbl_Comments as co
ON a.ActivityID = co.ActivityID
WHERE a.UnitID = 5 AND co.PeriodID = 1
) as aco
GROUP BY c.Category
) as aco
ON aco.CommentId = ac.CommentId
Note that your LEFT JOINs are superfluous because the WHERE clause turns them into INNER JOINs. This adjusts the logic for that purpose. The filtering is also very tricky, because it uses both tables, requiring that both subqueries have both JOINs.
You can use DISTINCT:
SELECT
tbl_Category.Category, Count(DISTINCT tbl_Activity.ActivityID) AS CountOfActivityID,
Count(DISTINCT tbl_Comments.CommentID) AS CountOfCommentID
FROM tbl_Category LEFT JOIN
(tbl_Activity LEFT JOIN tbl_Comments ON
tbl_Activity.ActivityID = tbl_Comments.ActivityID) ON
tbl_Category.CategoryID = tbl_Activity.CategoryID
WHERE
(((tbl_Activity.UnitID)=5) AND ((tbl_Comments.PeriodID)=1))
GROUP BY
tbl_Category.Category;

Access Subquery On mulitple conditions

This SQL query needs to be done in ACCESS.
I am trying to do a subquery on the total sales, but I want to link the sale to the province AND to product. The below query will work with one or the other: (po.product_name = allp.all_products) AND (p.province = allp.all_province); -- but it will no take both.
I will be including every month into this query, once I can figure out the subquery on with two criteria.
Select
p.province as [Province],
po.product_name as [Product],
all_price
FROM
(purchase_order po
INNER JOIN person p
on p.person_id = po.person_id)
left join
(
select
po1.product_name AS [all_products],
sum(pp1.price) AS [all_price],
p1.province AS [all_province]
from (purchase_order po1
INNER JOIN product pp1
on po1.product_name = pp1.product_name)
INNER JOIN person p1
on po1.person_id = p1.person_id
group by po1.product_name, pp1.price, p1.province
)
as allp
on (po.product_name = allp.all_products) AND (p.province = allp.all_province);
Make the first select sql into a table by giving it an alias and join table 1 to table 2. I don't have your table structure or data to test it but I think this will lead you down the right path:
select table1.*, table2.*
from
(Select
p.province as [Province],
po.product_name as [Product]
--removed this ,all_price
FROM
(purchase_order po
INNER JOIN person p
on p.person_id = po.person_id) table1
left join
(
select
po1.product_name AS [all_products],
sum(pp1.price) AS [all_price],
p1.province AS [all_province]
from (purchase_order po1
INNER JOIN product pp1
on po1.product_name = pp1.product_name)
INNER JOIN person p1
on po1.person_id = p1.person_id
group by po1.product_name, pp1.price, p1.province --check your group by, I dont think you want pp1.price here if you want to aggregate
) as table2 --changed from allp
on (table1.product = table2.all_products) AND (table1.province = table2.all_province);

SELECT records with condition that filters the last chronilogical multiple and specific value of a column

I have a joined table that looks like that:
my goal is to filter all records that was created after the last 'active' value inside LineStatusName Column. (the yellow marked rows in the attached image).
here is what i have done so far, it is almost work as desired, but the problem is that the date that returns from the nested select steatment is not the date of the highest chronological datetime value of 'active' and if i try to do ORDER BY Changes.ChangeDateTim in the end of the nested select i get a syntax error:
Conversion failed when converting the nvarchar value '30-9000241' to data type int.
I will be grateful if someone can suggest a better solution to achieve that task or to improve my query.
SELECT Orders.OrderID,LineStatuses.LineStatusName,OrderTypes.OrderTypeName,
Changes.ChangeDateTime,Orders.ProjectNumber,Changes.Comments,Changes.ChangeTypeID
FROM Orders
INNER JOIN Changes ON Changes.ItemID = Orders.OrderID
INNER JOIN LineStatusSettings ON LineStatusSettings.LineStatusSettingID = Changes.NewValue
INNER JOIN LineStatuses ON LineStatuses.LineStatusID= LineStatusSettings.LineStatusID
INNER JOIN OrderTypes ON OrderTypes.OrderTypeID = LineStatusSettings.OrderTypeID
WHERE Orders.OrderID = 194 AND Orders.Deleted=0
AND
Changes.ChangeDateTime > (
SELECT TOP 1 Changes.ChangeDateTime
FROM Orders
INNER JOIN Changes ON Changes.ItemID = Orders.OrderID
INNER JOIN LineStatusSettings ON LineStatusSettings.LineStatusSettingID = Changes.NewValue
INNER JOIN LineStatuses ON LineStatuses.LineStatusID= LineStatusSettings.LineStatusID
INNER JOIN OrderTypes ON OrderTypes.OrderTypeID = LineStatusSettings.OrderTypeID
WHERE LineStatuses.LineStatusName = 'active'
) AND OrderTypes.OrderTypeName NOT IN ('disconnected line')
ORDER BY Changes.ChangeDateTime
Here is one method:
with jt as (
<your query here>
)
select jt.*
from jt
where jt.date > (select max(jt2.date)
from jt jt2
where jt2.orderid = jt.orderid and jt2.linestatusname = 'Active'
);

How do I use a table name that's returned in a select statement, in a join?

*Note: This is not the same as the "possible duplicate". Here, the table name will be different for each record returned in the SELECT statement. So I can't just "set" a variable like set #tableName = 'whatever'.
Here's my SQL - take a look at my last inner join. e.Name from the table EmailSendDefintion is the name of the table I need to join to. So, this is kind of dynamic, I know, but how do I join to a table that is stored in a field in another table?
select top 5000
x.HL_ACCT_ID as 'HL_ACCT_ID',
x.SALE_CODE as 'SALE_CODE',
s.SubscriberKey as 'EmailAddress',
o.EventDate as 'Opened',
c.EventDate as 'Clicked',
b.EventDate as 'Bounced'
from c100._sent s with (nolock)
inner join c100._job j with (nolock) on s.jobid = j.jobid
inner join emailsenddefinition e with (nolock) on e.customerkey = j.emailsenddefinition
left join c100._open o with (nolock) on o.jobid = s.jobid and o.subscriberkey = s.subscriberkey
left join c100._click c with (nolock) on c.jobid = s.jobid and c.subscriberkey = s.subscriberkey
left join c100._bounce b with (nolock) on b.jobid = s.jobid and b.subscriberkey = s.subscriberkey
inner join c100.[e.name] x with (nolock) on x.EmailAddress = s.SubscriberKey
where e.clientid = 100
Perhaps you could just create a view that outputs the union of all the e.name tables? Then join to the view.
In order to keep this short, let's say you have just 2 different tables whose name could be in the e.name column, SubscriberEmail1 and SubscriberEmail2.
Then you could create a view like this:
CREATE VIEW SubscriberEmailUnion
AS
SELECT
'SubscriberEmail1' as TableName,
HL_ACCT_ID,
SALE_CODE,
EmailAddress
FROM SubscriberEmail1
UNION
SELECT
'SubscriberEmail2' as TableName,
HL_ACCT_ID,
SALE_CODE,
EmailAddress
FROM SubscriberEmail2
GO
Note that each part of the view is adding the name of it's underlying table as a column. You can then change your final join to:
inner join SubscriberEmailUnion x with (nolock) on (
x.EmailAddress = s.SubscriberKey
AND x.TableName = e.Name
)
I'm personally most familiar with MS Sql Server so my sample uses that syntax. Should be easy enough to change to work with a different server if necessary though.
For performance you can then use whatever feature your DB has, indexed views etc.
How many tables do you have? If not too many one option would be to left join all of them
left join c100.table1 x1 on x1.EmailAddress = s.SubscriberKey and [e.name] = 'table1'
left join c100.table2 x1 on x2.EmailAddress = s.SubscriberKey and [e.name] = 'table2'
etc...
and then in the select
coalesce(x1.HL_ACCT_ID, x2.HL_ACCT_ID, etc...) as 'HL_ACCT_ID',