Inner Join (Select . From) - sql

I need to get the last record posted by users. The following query below would get the information I need if I want if I can do order by before group by
select a.client_id, a.client, b.title, b.type, b.created
from profile_users a, node b
where a.uid = b.uid
and b.type = 'event'
and a.status=1
and a.client_id in (select c.client_id
from profile_users c, follows d
where c.uid = d.followed_id
and d.following_id =3)
group by a.client_id
order by a.client_id,
b.created desc
I tried rewriting the query using inner join but not getting the desired result. I need to write this query so that I am getting the client_id after checking records on follows table. I need some assistance to fix this query.
select b.client_id, b.client, a.title, a.created
from node a
inner join profile_users b on a.uid=b.uid
inner join (select c.client_id
from profile_users c
inner join follows d on c.uid=d.followed_id
where c.status = 1
and d.following_id = 3
order by c.client_id
) as X1

Use sql "partition by " it will allow you to sort your records without group by.
http://learnsqlserver.in/2/Partition-By-Clause.aspx
This is best to use over group by.

You need to use a co-related subquery in order to determine the last post:
select a.client_id, a.client, b.title, b.type, b.created
from profile_users a
join node b on a.uid = b.uid
where b.type = 'event'
and a.status=1
and a.client_id in (select c.client_id
from profile_users c
join follows d on c.uid = d.followed_id
where d.following_id = 3)
and b.created = (select max(n2.created)
from node n2
where n2.uid = a.uid)
order by a.client_id,
b.created desc
I also changed your old-style implicit joins in the where clause to explicit ones using the 'JOIN' keyword.

Related

How to find exact match of multiple values in a column?

I need a query that returns all picklists that only have the specified UPCs (e.g. 038447302 and 00934831). The query I am currently have is using WHERE IN and so it returns all picklists that have the specified UPCs as well as any other UPC in the picklist.
SELECT
a.order_id,
a.id AS picklist_id,
SUM(p.quantity),
p.upc,
pick_zone,
a.STATUS
FROM
picklists a
INNER JOIN picklist_items p ON p.picklist_id = a.id
INNER JOIN warehouse_orders f ON a.order_id = f.id
WHERE
a.STATUS IN ('dropped')
AND f.status != 'cancelled'
and p.upc IN('038447302', '00934831')
GROUP BY
a.STATUS,
a.picklist_group_id,
a.id,
a.order_id,
pick_zone

Replace correlated subquery with CTE and JOIN

I am trying to rewrite a query which has a correlated subquery, the idea is to replace it with a CTE and join it later.
I have three tables, tbl_transaction, tbl_beneficiaries and tbl_reg_countries. The current (in short) SQL looks like the following.
SELECT
t.USER_ID,
t.TRANSACTION
FROM tbl_transactions t
JOIN tbl_beneficiaries b ON b.ID = t.USER_ID
WHERE b.COUNTRY NOT IN (
SELECT rc.country
FROM tbl_reg_countries rc
WHERE rc.id = t.USER.ID)
My goal is to query only those transactions for each user where the transaction happens outside of the registered countries. So a user may registered X,Y,Z country but had business with Q. In that case only Q should be returned. How could this be replaced with a CTE/JOIN?
I assume both tbl_beneficiaries.COUNTRY and tbl_reg_countries.COUNTRY are not nullable. You can use a LEFT JOIN with NULL test to detect never matching rows
SELECT
t.USER_ID,
t.TRANSACTION
FROM tbl_transactions t
JOIN tbl_beneficiaries b ON b.ID = t.USER_ID
LEFT JOIN tbl_reg_countries rc ON rc.id = t.USER_ID AND b.COUNTRY = rc.country
WHERE rc.country IS NULL
I would try rewriting query with "with"
Like this:
With a As
(Select
Distinct rc.country
From tbl_reg_countries rc
Inner Join tbl_transactions t on rc.id = t.USER.ID
)
Select
t.USER_ID,
t.TRANSACTION
From tbl_transactions t
Inner Join tbl_beneficiaries b On b.ID = t.USER_ID
Where b.COUNTRY Not In (select * from a)

Query the results of another query

I'm writing a query to build an audience for a abandoned cart email. So far, I have the script below, which gives me the correct result (as far as I can tell). However, if possible I would like to query the final result, in order to:
Check if there are multiples of the same email_address that exist in the
output
If true, select the email_address with the oldest (min) modified_date
email_address exist in table a, but I want to use the modified_date from table c.
Can anybody assist me?
Also, I'm not an sql dev, so if you could please explain your answer to help me learn, I would grateful.
Thanks in advance.
SELECT DISTINCT a.guid,
a.customer_id,
a.email_address,
c.product_code,
c.purchase_url,
c.modified_date
FROM (SELECT LIST.guid,
LIST.customer_id,
LIST.email_address
FROM $a$ LIST) a
INNER JOIN (SELECT BASE.guid
FROM $b$ BASE) b
ON a.guid = b.guid
INNER JOIN (SELECT SUPP.customer_id,
SUPP.product_code,
SUPP.purchase_url,
SUPP.modified_date
FROM $c$ SUPP) c
ON a.customer_id = c.customer_id
LEFT JOIN (SELECT EXCL.product_code
FROM $d$ EXCL) d
ON c.product_code = d.product_code
WHERE d.product_code IS NULL
AND c.product_code IS NOT NULL
AND c.modified_date = (SELECT Max(J.modified_date)
FROM $c$ J
WHERE J.customer_id = c.customer_id)
AND Trunc(c.modified_date) = Trunc(sysdate) - 1
If you just need email_address with mininum modified_date you can use below query:
SELECT DISTINCT a.guid,
a.customer_id,
a.email_address,
c.product_code,
c.purchase_url,
min(c.modified_date)over(partition by a.email_address)modified_date
FROM (SELECT LIST.guid,
LIST.customer_id,
LIST.email_address
FROM $a$ LIST) a
INNER JOIN (SELECT BASE.guid
FROM $b$ BASE) b
ON a.guid = b.guid
INNER JOIN (SELECT SUPP.customer_id,
SUPP.product_code,
SUPP.purchase_url,
SUPP.modified_date
FROM $c$ SUPP) c
ON a.customer_id = c.customer_id
LEFT JOIN (SELECT EXCL.product_code
FROM $d$ EXCL) d
ON c.product_code = d.product_code
WHERE d.product_code IS NULL
AND c.product_code IS NOT NULL
AND c.modified_date = (SELECT Max(J.modified_date)
FROM $c$ J
WHERE J.customer_id = c.customer_id)
AND Trunc(c.modified_date) = Trunc(sysdate) - 1

How to construct a SQL sub query in SQL Server 2008?

I have requirement to extract total number of rows from a table - ci_periodicBillings only for clients where they have rows from a particular date range from another table - ci_invoiceHeaders. I am using MS SQL Server 2008, connecting via ODBC.
I have created a subquery which works but only if the total number of rows from ci_periodicBillings is 1. I'm finding if there is more than 1 result from ci_periodicBillings, it's multiplying the rows found by the number of rows meeting the criteria from ci_invoiceHeaders.
I only want to show only the rows from ci_periodicBillings without any multiplication if the criteria is met in ci_invoiceHeaders. I'm sure there is an easy solution to this but I can't see the wood from the trees at the moment.
There are a few other tables used for listing purposes only (i.e. facilities/clients etc)
SQL is here:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT
b.name,
b.forename,
b.surname,
a.client,
cast(a.BILLSTART as DATE) as BILLSTART,
cast(a.ENDBILL as DATE) as ENDBILL,
a.RATE
FROM ci_periodicBillings as a
inner join
(select f.name,
c.surname,c.forename,ih.client,ih.invoiceDate
FROM ci_invoiceHeaders ih
LEFT JOIN ci_invoiceDetails id ON ih.invoiceNo = id.id
INNER JOIn cs_clients c ON ih.client = c.guid
INNER JOIN cs_facilities f ON c.facility = f.guid
group by f.name, c.surname,
c.forename, ih.client, ih.invoiceDate)
as b
on a.client = b.client
WHERE b.invoiceDate between '2017-08-01' and '2018-01-31'
order by a.client
Any ideas please?
Try this:
SELECT b.name, b.forename, b.surname, a.client,
cast(a.BILLSTART AS DATE) AS BILLSTART,
cast(a.ENDBILL AS DATE) AS ENDBILL, a.RATE
FROM ci_periodicBillings AS a inner join
(SELECT f.name, c.surname,c.forename,ih.client,DATE(ih.invoiceDate) invoiceDate
FROM ci_invoiceHeaders ih
LEFT JOIN ci_invoiceDetails id ON ih.invoiceNo = id.id
INNER JOIn cs_clients c ON ih.client = c.guid
INNER JOIN cs_facilities f ON c.facility = f.guid
WHERE ih.invoiceDate BETWEEN '2017-08-01' AND '2018-01-31'
GROUP BY f.name, c.surname,c.forename,ih.client,DATE(ih.invoiceDate)) AS b
ON a.client = b.client
ORDER BY a.client;

SQL Query to do an INNER JOIN based on 3 different tables

Initially, let me describe what I want my query to return. I want this query to return all of the records from the Address table which have an AddressTypeLookupID of either 3 or 5, which is set in the AddressType table. Second, as a further restriction, this must also include only companies with IndustryTypeID = 56, which is set in the IndustryType table. All records in the Address, AddressType, and IndustryType tables are linked by ID.
SELECT B.AddressTypeLookupID, A.Address1, A.Address2, A.City, A.State, A.Zip, A.ID
FROM Company.dbo.Address A
INNER JOIN Company.dbo.AddressType B ON A.AddressID = B.AddressID
WHERE B.Status = 'Active' AND
B.AddressTypeLookupID = 3 AND
A.AddressID = (SELECT MAX(Z.AddressID)
FROM Company.dbo.Address Z
INNER JOIN Company.dbo.AddressType X ON Z.AddressID = X.AddressID
WHERE B.Status = 'Active'
AND B.AddressTypeLookupID = 3
AND Z.ID = A.ID
)
INNER JOIN COMPANY.dbo.IndustryTypeCompanyName g ON g.ID = A.ID
WHERE g.IndustryTypeID = 56
UNION ALL
SELECT B.AddressTypeLookupID, A.Address1, A.Address2, A.City, A.State, A.Zip, A.ID
FROM Company.dbo.Address A
INNER JOIN Company.dbo.AddressType B ON A.AddressID = B.AddressID
WHERE B.Status = 'Active' AND
B.AddressTypeLookupID = 5 AND
A.AddressID = (SELECT MAX(Z.AddressID)
FROM Company.dbo.Address Z
INNER JOIN Company.dbo.AddressType X ON Z.AddressID = X.AddressID
WHERE B.Status = 'Active' AND
B.AddressTypeLookupID = 5 AND
Z.ID = A.ID
)
INNER JOIN COMPANY.dbo.IndustryTypeCompanyName j ON j.ID = A.ID
WHERE j.IndustryTypeID = 56
My issue is, I believe, with the inner joins called 'g' and 'j' above, where I try to restrict the query by IndustryTypeID = 56. The query works properly (as desired) without these lines. I am simply having trouble restricting the (full) query by IndustryTypeID to be 56. I either am wrong in my logic, am or I simply not understanding SQL syntax. I am using Microsoft SQL Management Studio 2008.
I'm not sure what the last join is supposed to mean, but as far as I can tell your query can be simplified to:
SELECT B.AddressTypeLookupID, A.Address1, A.Address2, A.City, A.State, A.Zip, A.ID
FROM Company.dbo.Address A
JOIN Company.dbo.AddressType B
ON A.AddressID = B.AddressID
JOIN COMPANY.dbo.IndustryTypeCompanyName g
ON g.ID = A.ID
WHERE B.Status = 'Active'
AND B.AddressTypeLookupID in (3,5)
AND A.AddressID = ( SELECT MAX(Z.AddressID)
FROM Company.dbo.Address Z
JOIN Company.dbo.AddressType X
ON Z.AddressID = X.AddressID
WHERE
-- redundant predicates removed
-- B.Status = 'Active'
-- AND B.AddressTypeLookupID = 3
-- AND
Z.ID = A.ID
)
AND g.IndustryTypeID = 56
I see the issue now that we know it is a syntax error. You have an inner join, a where, then another inner join, then another where. Each group can only occur once in the requried order, but you can use the keyword join more than once. So select, from, join, join where.
SELECT B.AddressTypeLookupID, A.Address1, A.Address2, A.City, A.State, A.Zip, A.ID
FROM Company.dbo.Address A
INNER JOIN Company.dbo.AddressType B
ON A.AddressID = B.AddressID
INNER JOIN COMPANY.dbo.IndustryTypeCompanyName g
ON g.ID = A.ID
WHERE B.Status = 'Active'
AND B.AddressTypeLookupID = 3
AND A.AddressID =
(SELECT MAX(Z.AddressID)
FROM Company.dbo.Address Z
INNER JOIN Company.dbo.AddressType X
ON Z.AddressID = X.AddressID
WHERE B.Status = 'Active'
AND B.AddressTypeLookupID = 3
AND Z.ID = A.ID
)
AND g.IndustryTypeID = 56
Since your already including the address table in your select rather than selecting max it would be easier to just use ROW_NUMBER() to solve your 1 per group problem
With cte as
(
SELECT B.addresstypelookupid,
A.address1,
A.address2,
A.city,
A.state,
A.zip,
A.id ,
ROW_NUMBER() OVER (Partition BY b.addresstypelookupid
order by addressid desc ) rn
FROM company.dbo.address A
INNER JOIN company.dbo.addresstype B
ON A.addressid = B.addressid
AND B.addresstypelookupid IN ( 3, 5 )
AND B.status = 'Active'
INNER JOIN company.dbo.industrytypecompanyname g
ON g.id = A.id
WHERE g.industrytypeid = 56
)
SELECT * FROM CTE WHERE Rn = 1