ANSI SQL question - sql

I have a table which has fields (id, parent_id, name, created_at). I want to write a query to select id, name, created_at, parent_created_at. The 'parent_created_at' is the 'created_at' field for the records matching parent (if it has one - i.e. the records parent_id >0), otherwise the 'parent_created_at' field should be null. Any suggestions?

Self Join + ANSI SQL CASE Expression
SELECT t.id
, t.name
, t.created_at
, CASE WHEN t.parent_id > 0 THEN p.created_at ELSE NULL END AS parent_created_at
FROM Table t
JOIN Table p
ON t.id = p.parent_id

Morpheous,
You only have two rows in your table, so please take the trouble to give all the details! All you tell us is what their parent_ids are, and your query's join condition depends on more than that.
Can you fill in the ... below so we know the full details?
CREATE TABLE t(...
INSERT INTO t VALUES (...
INSERT INTO t VALUES (...

Related

How to loop statements in SQL Server

I am new to SQL Server, I am trying to do something as follows.
Sample code :
SELECT ITEM_ID
FROM 'TABLE_NAME_1'
WHERE ITEM_STATUS = 'ACTIVE'
SET #ITEM_PRICE = (SELECT PRICE
FROM 'TABLE_NAME_2'
WHERE 'PRODUCT_ID' = 'ITEM_ID')
INSERT INTO 'TABLE_NAME_3' (ITEM_ID, PRICE)
VALUES (#ITEM_ID, #ITEM_PRICE)
The first statement will return multiple rows of ITEM_ID
By using the ITEM_ID I need to select the ITEM_PRICE from another table using the second statement
By using the third statement, I need to insert the data into the third table
Here the first statement returns only one ITEM_ID, then everything is easy to do. I f it returns multiple rows how can I do all these processes for all the ITEM_ID which has returned by the first statement?
Actually, If the first statement returns 5 rows I need to loop 5 times.
Is it possible in SQL Server, if yes, please help me to do this
Question would be why not use a straight SQL
INSERT
INTO 'TABLE_NAME_3'
(ITEM_ID
,PRICE
)
SELECT ITEM_ID,ITEM_PRICE
FROM 'TABLE_NAME_1' A
JOIN 'TABLE_NAME_2' B
ON A.ITEM_ID=B.PRODUCT_ID
WHERE A.ITEM_STATUS = 'ACTIVE'
based on your question i have created sample code you can use only one query to insert multiple data if you want to insert common data between table 1 and table 2 then use inner join or left join will be fine.
Code
INSERT INTO 'TABLE_NAME_3' (ITEM_ID,PRICE)
SELECT T1.ITEM_ID , T2.PRICE
FROM 'TABLE_NAME_1' AS T1
INNER JOIN 'TABLE_NAME_2' AS T2 ON T2.PRODUCT_ID = T1.ITEM_ID
WHERE T1.ITEM_STATUS = 'ACTIVE'

How can I grab one column from a subquery and insert that column into another table where I can query off of those ID's in another data table?

Trying to explain this the best I can, I have a subquery which is looking for some document information in one table, I need to then use an INSERT INTO to ONLY take the document IDs that are returned and query them in a separate data table.
This is what Im working with right now
use DATABASE
Select * into #Audit
From [dbo].[workflow] A
Where object_id IN
(
Select DISTINCT ChangeHistory.document_id, ChangeHistory.account_number,
min(timestamp)
from [dbo].[xip_workflow] A
INNER JOIN (select B.*
from [dbo].[changehistory] B
where B.doc_status like ('New')
and user_login_name like ('System')
and button_push like (' ')
and B.account_number in ('11111111')
and B.work_queue_system_name in ('r_queue')
and B.document_type in ('A1','A2','A3')
and timestamp > '4/11/2017') ChangeHistory
ON ChangeHistory.[document_id] = A.[object_id]
group by document_id, ChangeHistory.account_number)

How can I append records that don't already exist in a table from a cartesian product query?

My current query returns every possible outcome from 2 tables and inserts them into a junction table.
My current query looks like this:
INSERT INTO tblJunction_Courses_Software ( CourseID, SoftwareID )
SELECT tblCourses.CourseID, tblSoftware.SoftwareID
FROM tblSoftware, tblCourses
WHERE (((tblSoftware.Exclude)=No));
How can I add an additional clause to make sure that duplicate data is not appended every time the query is run?
I think you can do what yo want with a not exists clause:
INSERT INTO tblJunction_Courses_Software ( CourseID, SoftwareID )
SELECT c.CourseID, s.SoftwareID
FROM tblSoftware as s CROSS JOIN tblCourses as c
WHERE s.Exclude = No AND
NOT EXISTS (SELECT 1
FROM tblJunction_Courses_Software as cs
WHERE cs.CourseId = c.CourseId AND
cs.SoftwareId = s.SOftwareId
);

Need help understanding a complex query with multiple join conditions

I have a query that I am trying to understand. Can someone shed light on to the details of what this query does?
I've only ever used one ON clause in a join condition. This one has multiple conditions for the LEFT JOIN, making it tricky to understand.
INSERT INTO nop_tbl
(q_date, community_id, newsletter_t, subscription_count)
SELECT date(now()), a.community_id,
a.newsletter_type,
count(a.subscriber_user_id)
FROM
newsletter_subscribers_main a
LEFT OUTER JOIN nop_tbl b
ON (a.community_id = b.community_id)
AND (a.newsletter_type = b.newsletter_t)
AND (a.created_at = b.q_date)
WHERE b.q_date is null
AND b.mailing_list is null
GROUP BY a.community_id, a.newsletter_t, a.created_at
You have your explanation:
The objective of the query is to count subscriptions per (q_date, community_id, newsletter_t) in newsletter_subscribers_main and write the result to nop_tbl.
The LEFT JOIN prevents that rows are added multiple times.
But I also think, the query is inefficient and probably wrong.
The 2nd WHERE clause:
AND b.mailing_list is null
is just noise and can be removed. If b.q_date is null, then b.mailing_list is guaranteed to be null in this query.
You don't need parentheses around JOIN conditions.
If subscriber_user_id is defined NOT NULL, count(*) does the same, cheaper.
I suspect that grouping by a.created_at, while you insert date(now()) is probably wrong. Hardly makes any sense. My educated guess (assuming that created_at is type date):
INSERT INTO nop_tbl
(q_date, community_id, newsletter_t, subscription_count)
SELECT a.created_at
,a.community_id
,a.newsletter_type
,count(*)
FROM newsletter_subscribers_main a
LEFT JOIN nop_tbl b ON a.community_id = b.community_id
AND a.newsletter_type = b.newsletter_t
AND a.created_at = b.q_date
WHERE b.q_date IS NULL
GROUP BY a.created_at, a.community_id, a.newsletter_t;
The short short version is:
insert ... select ...
-> the query is filling nob_tbl
from ...
-> based on data in newsletter_subscribers_main
left join ... where ... is null
-> that are not already present in nob_tbl
Step by step
INSERT INTO nop_tbl
(q_date, community_id, newsletter_t, subscription_count)
The INSERT syntax This is telling the database in what table and what column will be used for the insert query
SELECT date(now()), a.community_id,
a.newsletter_type,
count(a.subscriber_user_id)
Those are instead the selected fields to insert
FROM
newsletter_subscribers_main a
Here is telling to the database to select fields which has alias prepended a. from table newsletter_subscribers_main
LEFT OUTER JOIN nop_tbl b
Here is left joining another table nop_tbl where other fields will be selected
ON (a.community_id = b.community_id)
AND (a.newsletter_type = b.newsletter_t)
AND (a.created_at = b.q_date)
Those are the rules of the JOIN, actually is telling what columns will be used for join
WHERE b.q_date is null
AND b.mailing_list is null
Those are the WHERE clauses , they are used to limit result to the requested data, in this case where two columns are null
GROUP BY a.community_id, a.newsletter_t, a.created_at
GROUP BY clauses, used to group result on given column
You can have a visual explanation of joins here

SQL, only if matching all foreign key values to return the record?

I have two tables
Table A
type_uid, allowed_type_uid
9,1
9,2
9,4
1,1
1,2
24,1
25,3
Table B
type_uid
1
2
From table A I need to return
9
1
Using a WHERE IN clause I can return
9
1
24
SELECT
TableA.type_uid
FROM
TableA
INNER JOIN
TableB
ON TableA.allowed_type_uid = TableB.type_uid
GROUP BY
TableA.type_uid
HAVING
COUNT(distinct TableB.type_uid) = (SELECT COUNT(distinct type_uid) FROM TableB)
Join the two tables togeter, so that you only have the records matching the types you are interested in.
Group the result set by TableA.type_uid.
Check that each group has the same number of allowed_type_uid values as exist in TableB.type_uid.
distinct is required only if there can be duplicate records in either table. If both tables are know to only have unique values, the distinct can be removed.
It should also be noted that as TableA grows in size, this type of query will quickly degrade in performance. This is because indexes are not actually much help here.
It can still be a useful structure, but not one where I'd recommend running the queries in real-time. Rather use it to create another persisted/cached result set, and use this only to refresh those results as/when needed.
Or a slightly cheaper version (resource wise):
SELECT
Data.type_uid
FROM
A AS Data
CROSS JOIN
B
LEFT JOIN
A
ON Data.type_uid = A.type_uid AND B.type_uid = A.allowed_type_uid
GROUP BY
Data.type_uid
HAVING
MIN(ISNULL(A.allowed_type_uid,-999)) != -999
Your explanation is not very clear. I think you want to get those type_uid's from table A where for all records in table B there is a matching A.Allowed_type_uid.
SELECT T2.type_uid
FROM (SELECT COUNT(*) as AllAllowedTypes FROM #B) as T1,
(SELECT #A.type_uid, COUNT(*) as AllowedTypes
FROM #A
INNER JOIN #B ON
#A.allowed_type_uid = #B.type_uid
GROUP BY #A.type_uid
) as T2
WHERE T1.AllAllowedTypes = T2.AllowedTypes
(Dems, you were faster than me :) )