September 30, 2017 at 1:36 pm
Hi Experts,
I have written a query based on our requirement using co-related sub-query.
Checking if this can re-written using a JOIN instead of co-related subquery? Mainly, 5th column in the SELECT list. How can we implement using a join, I tried but it was throwing error saying, columns which aren't in GROUP BY cannot be
selected in the select list. So, I have written using a co-related subquery. There is nothing wrong in this approach, would like to know, if it has to rewritten using a join in the FROM clause, then how to do that?
SELECT
t1.[Accno],
t2.[CustomerName],
t2.[High Rate] AS Ceiling_Rate,
t3.[Low Rate] AS Floor_Rate,
(SELECT max(b.[Maturity_Date]) FROM t4 as b WHERE b.[Account Number] = t1.[Accno] and b.[Maturity_Date] is not null and len(b.[Maturity_Date])>0 ) AS [Payoff_Date]
FROM AS t1
LEFT JOIN t2 ON t1.[Accno]=t2.[Accno]
LEFT OUTER JOIN t3 on t1.[Accno] = t3.[Account Number];
Thank you.
Sam
September 30, 2017 at 3:58 pm
We need more information before we can help you. Did you read the part in the front of this form about posting DDL? You need to do that before anything else can help you.
You have four tables, which you name as if they were 1950 tape drives. The difference is we usually started with "MT0:" and then increased it by one. In SQL. These tables should have meaningful names, based on ISO 11179 naming rules. It looks like the account information is separated from the customer order. That makes no sense. Then the rate of something has its high and low ranges spread out over two separate tables. Again, that makes no sense. What you're saying is that all of these things are so totally different and unrelated, they go in separate tables. But this looks like a design flaw called attribute splitting, where things that are attributes of the same entity appear in multiple places in the schema instead of with that entity.
SQL has a date data type, which is nothing whatsoever like a string. This means looking for the link of this data element is absurd on the face of it. It's like asking what color is your favorite letter of the alphabet on a scale from 1 to 10.
Please stop using the square brackets and embedded spaces. This is more of your tape file mentality showing up; you're embedding spaces so you can do display formatting in the database layer, instead of in the presentation layer layer where might belong. You also use aliases to rename data elements; one of the first principles of RDBMS is at a data element has one and only one name everywhere. What makes a "maturity date" a totally different attribute from a "payoff date" in your data model?
This is why we use what is called a role as a prefix on a data element, we need to distinguish between things like the various rates
SELECT T1.account_nbr, T2.customer_name,
T2.high_something_rate, T3.low_something_rate,
(SELECT MAX(T4.maturity_date)
FROM T4
WHERE T4.account_nbr = T1.account_nbr
AND T4.maturity_date IS NOT NULL
AND LEN(B.maturity_date) > 0) AS payoff_date
FROM (T1
LEFT OUTER JOIN
T2
ON T1.account_nbr = T2.account_nbr
LEFT OUTER JOIN T3
ON T1.account_nbr = T3.account_nbr; name
Based on nothing I've got to work with here, I'm going to make some guesses about tables that we can see, keys, references and constraints we were not given. My first guess is that if your design was correct. You're probably have all this information in a single table probably called accounts.
SELECT A.account_nbr, A.customer_name,
A.high_something_rate, A.low_something_rate,
A.maturity_date
FROM Accounts AS A;
Please post DDL and follow ANSI/ISO standards when asking for help.
September 30, 2017 at 6:31 pm
Without an actual execution plan. table structure or index info, we're just stabbing in the wind... Based on the code pattern alone... Here a few alternatives that are logically equivalent but likely to produce different execution plans,
Test them all against you data... One or two is likely to produce a plan that is is far better than the others...
-- option 1... sinle scan of T4
-- good option if account number has low density.
-- meaning lots of different numbers, none of which represent a large proportion of the total rows.
-- or there isn't a great index available for T5
SELECT
t1.Accno,
t2.CustomerName,
Ceiling_Rate = t2.[High Rate],
Floor_Rate = t3.[Low Rate],
Payoff_Date
FROM
dbo.t1
LEFT JOIN t2
ON t1.Accno = t2.Accno
LEFT JOIN t3
ON t1.Accno = t3.[Account Number]
LEFT JOIN (
SELECT
b.[Account Number],
Payoff_Date = MAX(b.Maturity_Date)
FROM
t4 AS b
WHERE
b.Maturity_Date IS NOT NULL
) mmd
ON t1.Accno = mmd.[Account Number];
-- option 2... another single scan option ... BUT...
-- that scan will be an ordered scan which will be stupid fast with a "POC" index on T4
-- the POC indec would have account number in the 1st position and maturity date in the 2nd position.
WITH
cte_MaxMaturity AS (
SELECT
b.[Account Number],
b.Maturity_Date,
RN = ROW_NUMBER() OVER (PARTITION BY b.[Account Number] ORDER BY b.Maturity_Date DESC)
FROM
t4 AS b
WHERE
b.Maturity_Date IS NOT NULL
)
SELECT
t1.Accno,
t2.CustomerName,
Ceiling_Rate = t2.[High Rate],
Floor_Rate = t3.[Low Rate],
Payoff_Date
FROM
dbo.t1
LEFT JOIN t2
ON t1.Accno = t2.Accno
LEFT JOIN t3
ON t1.Accno = t3.[Account Number]
LEFT JOIN cte_MaxMaturity mm
ON ON t1.Accno = mm.[Account Number];
-- option 3... Better for high density
-- or there is a light wight index on T4 with Account number in the 1st key position
-- and Maturity_Date as the second key position (prefferably with Maturity_Date in DESC order)
-- sort will be nast without the afformentioned index...
SELECT
t1.Accno,
t2.CustomerName,
Ceiling_Rate = t2.[High Rate],
Floor_Rate = t3.[Low Rate],
Payoff_Date
FROM
dbo.t1
LEFT JOIN t2
ON t1.Accno = t2.Accno
LEFT JOIN t3
ON t1.Accno = t3.[Account Number]
OUTER APPLY (
SELECT TOP (1)
Payoff_Date = b.Maturity_Date
FROM
t4 AS b
WHERE
t1.Accno = b.[Account Number]
AND b.Maturity_Date IS NOT NULL
ORDER BY
b.Maturity_Date DESC
) mmd;
-- option 4... Better for high density
-- or there is a light wight index on T4 with Account number in the 1st key position
-- better option than option 3 IF... the index doesn't have Maturity_Date in the 2nd key position.
SELECT
t1.Accno,
t2.CustomerName,
Ceiling_Rate = t2.[High Rate],
Floor_Rate = t3.[Low Rate],
Payoff_Date
FROM
dbo.t1
LEFT JOIN t2
ON t1.Accno = t2.Accno
LEFT JOIN t3
ON t1.Accno = t3.[Account Number]
OUTER APPLY (
SELECT
Payoff_Date = MAX(b.Maturity_Date)
FROM
t4 AS b
WHERE
t1.Accno = b.[Account Number]
AND b.Maturity_Date IS NOT NULL
) mmd;
October 1, 2017 at 11:50 am
Thanks Jason for the help.
October 1, 2017 at 11:48 pm
vsamantha35 - Sunday, October 1, 2017 11:50 AMThanks Jason for the help.
Glad to help. Hopefully one of those should help.
Viewing 5 posts - 1 through 4 (of 4 total)
You must be logged in to reply to this topic. Login to reply
This website stores cookies on your computer.
These cookies are used to improve your website experience and provide more personalized services to you, both on this website and through other media.
To find out more about the cookies we use, see our Privacy Policy