Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Alternative to PARTITION BY

Author  Topic 

kbrizendine
Starting Member

12 Posts

Posted - 2008-05-21 : 16:42:47
I have a situation where my SQL works everywhere else but my COBOL compiler complains wherever I use PARTITION BY. I can't find a workaround for that problem so I would like to remove all the PARTITION BYs. I'm not confident that I can do this accurately and would like some help getting started.

Here is my simplest example:

SELECT FESOR.REGION, FESOR.TYPE,
COUNT(*) OVER (PARTITION BY FESOR.REGION, FESOR.TYPE)
FROM FESOR, FR
where FESOR.phase = 'Ref'
and FESOR.assign is null
and FESOR.comp_date is null
and FESOR.region = FR.REGION
and FESOR.type = FR.TYPE
and FR.REP_ROW='A'
GROUP BY FESOR.REGION, FESOR.TYPE

What I'm looking for is a modified version of the SQL above which returns the same result set without using PARTITION BY.

Thanks in advance for your assistance.

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2008-05-21 : 16:44:12
You can use a correlated subquery instead and see performance go down the drain.



E 12°55'05.25"
N 56°04'39.16"
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-05-22 : 01:53:50
quote:
Originally posted by kbrizendine

I have a situation where my SQL works everywhere else but my COBOL compiler complains wherever I use PARTITION BY. I can't find a workaround for that problem so I would like to remove all the PARTITION BYs. I'm not confident that I can do this accurately and would like some help getting started.

Here is my simplest example:

SELECT FESOR.REGION, FESOR.TYPE,
COUNT(*) OVER (PARTITION BY FESOR.REGION, FESOR.TYPE) FROM FESOR, FR
where FESOR.phase = 'Ref'
and FESOR.assign is null
and FESOR.comp_date is null
and FESOR.region = FR.REGION
and FESOR.type = FR.TYPE
and FR.REP_ROW='A'
GROUP BY FESOR.REGION, FESOR.TYPE

What I'm looking for is a modified version of the SQL above which returns the same result set without using PARTITION BY.

Thanks in advance for your assistance.



I really cant understand the significance of PARTITION BY here since you're already grouping on the region & type.
Go to Top of Page

kbrizendine
Starting Member

12 Posts

Posted - 2008-05-22 : 09:45:06
quote:
Originally posted by Peso

You can use a correlated subquery instead and see performance go down the drain.



Could you indulge me with the modified SQL?
Go to Top of Page

kbrizendine
Starting Member

12 Posts

Posted - 2008-05-22 : 09:48:44
quote:
Originally posted by visakh16


I really cant understand the significance of PARTITION BY here since you're already grouping on the region & type.



I see what you mean - but I'm doing my best not to concern myself with the business purpose of the code. I have a bunch of these to fix so I'm just using the result set as a test of success instead of trying to understand each and every one of them.
Go to Top of Page

kbrizendine
Starting Member

12 Posts

Posted - 2008-05-22 : 13:46:40
quote:
Originally posted by kbrizendine

quote:
Originally posted by Peso

You can use a correlated subquery instead and see performance go down the drain.



Could you indulge me with the modified SQL?



I've been looking into your suggestion and it seems like it is the only way EXCEPT that, unless I'm mistaken, I would need a unique key in order to implement a correlated subquery however these tables do not have unique keys. Do you agree with my conclusion that the only solution is to add a unique key to one or both tables?
Go to Top of Page

Lamprey
Master Smack Fu Yak Hacker

4614 Posts

Posted - 2008-05-22 : 14:06:32
So is this query dynamic sql? I'm assuming that is the case since it is a COBOL compiler complaining. At anyratem I don't see why you need the OVER clause anyway:
SELECT 
FESOR.REGION,
FESOR.TYPE,
COUNT(*)
FROM
FESOR,
INNER JOIN
FR
ON FESOR.region = FR.REGION
AND FESOR.type = FR.TYPE
where
FESOR.phase = 'Ref'
and FESOR.assign is null
and FESOR.comp_date is null
and FR.REP_ROW='A'
GROUP BY
FESOR.REGION,
FESOR.TYPE
Go to Top of Page

kbrizendine
Starting Member

12 Posts

Posted - 2008-05-22 : 16:02:38
quote:
Originally posted by Lamprey

So is this query dynamic sql? I'm assuming that is the case since it is a COBOL compiler complaining. At anyratem I don't see why you need the OVER clause anyway:
SELECT 
FESOR.REGION,
FESOR.TYPE,
COUNT(*)
FROM
FESOR,
INNER JOIN
FR
ON FESOR.region = FR.REGION
AND FESOR.type = FR.TYPE
where
FESOR.phase = 'Ref'
and FESOR.assign is null
and FESOR.comp_date is null
and FR.REP_ROW='A'
GROUP BY
FESOR.REGION,
FESOR.TYPE




The result set from that SQL is this:

REGION_0 TYPE_a 4
REGION_0 TYPE_b 4
REGION_1 TYPE_a 4
REGION_1 TYPE_b 4
REGION_2 TYPE_a 1
REGION_2 TYPE_b 1

Whereas the results set from the original SQL is this:
(This is the result set I am trying to match)

REGION_0 TYPE_a 1
REGION_0 TYPE_b 1
REGION_1 TYPE_a 1
REGION_1 TYPE_b 1
REGION_2 TYPE_a 1
REGION_2 TYPE_b 1
Go to Top of Page

Lamprey
Master Smack Fu Yak Hacker

4614 Posts

Posted - 2008-05-22 : 18:07:13
Ahh try this:
SELECT 
FESOR.REGION,
FESOR.TYPE,
1
FROM
FESOR,
INNER JOIN
FR
ON FESOR.region = FR.REGION
AND FESOR.type = FR.TYPE
where
FESOR.phase = 'Ref'
and FESOR.assign is null
and FESOR.comp_date is null
and FR.REP_ROW='A'
GROUP BY
FESOR.REGION,
FESOR.TYPE
Go to Top of Page

kbrizendine
Starting Member

12 Posts

Posted - 2008-05-23 : 10:38:33
quote:
Originally posted by Lamprey

Ahh try this:
SELECT 
FESOR.REGION,
FESOR.TYPE,
1
FROM
FESOR,
INNER JOIN
FR
ON FESOR.region = FR.REGION
AND FESOR.type = FR.TYPE
where
FESOR.phase = 'Ref'
and FESOR.assign is null
and FESOR.comp_date is null
and FR.REP_ROW='A'
GROUP BY
FESOR.REGION,
FESOR.TYPE




Lol - I hope you're joking because otherwise you must think I'm an idiot.
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2008-05-23 : 10:46:11
Why not? It produces the resultset you wanted.



E 12°55'05.25"
N 56°04'39.16"
Go to Top of Page

kbrizendine
Starting Member

12 Posts

Posted - 2008-05-23 : 11:05:22
quote:
Originally posted by Peso

Why not? It produces the resultset you wanted.



E 12°55'05.25"
N 56°04'39.16"




If I just wanted those characters to appear on my computer screen I could copy and paste them like I did above.

Or maybe I could use this SQL statement:

select
'REGION_0 TYPE_a 1'
UNION ALL
select 'REGION_0 TYPE_b 1'
UNION ALL
select 'REGION_1 TYPE_a 1'
UNION ALL
select 'REGION_1 TYPE_b 1'
UNION ALL
select 'REGION_2 TYPE_a 1'
UNION ALL
select 'REGION_2 TYPE_b 1'
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2008-05-23 : 11:22:00
Excellent.
You haven't given us some proper sample data to work with so why not?
All you have given us is the wrong resultset, and the resultset you want to be returned.

But based on what?

See both
http://weblogs.sqlteam.com/jeffs/archive/2008/05/13/question-needed-not-answer.aspx
and
http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx



E 12°55'05.25"
N 56°04'39.16"
Go to Top of Page

Arnold Fribble
Yak-finder General

1961 Posts

Posted - 2008-05-23 : 12:31:05
quote:
Originally posted by kbrizendine
Lol - I hope you're joking because otherwise you must think I'm an idiot.



I think you're missing the point: if you have a count(*) that's partitioned over the same columns that you're grouping by, the answer is necessarily 1. So Lamprey's replacement of the count with just 1 is entirely legitimate.
Go to Top of Page

Lamprey
Master Smack Fu Yak Hacker

4614 Posts

Posted - 2008-05-23 : 12:38:10
quote:
Originally posted by kbrizendine
Lol - I hope you're joking because otherwise you must think I'm an idiot.

I don't think your an idiot. I just don't think you understand the SQL you have posted.

If you examine your origial query you will see that you are grouping by two columns FESOR.REGION and FESOR.TYPE. So trying to get a COUNT using the OVER operater by PARTITIONING on FESOR.REGION and FESOR.TYPE will always result in a COUNT of 1.

So, again, I don't see why you need to use a COUNT since the value is always 1. Here is a sample of what happens:
DECLARE @Foo TABLE (ID INT, Val INT)

INSERT @Foo
SELECT 1, 2
UNION ALL SELECT 1, 2
UNION ALL SELECT 2, 3
UNION ALL SELECT 3, 4

SELECT
ID,
Val,
COUNT(*) OVER (PARTITION BY ID, Val) aS MyCount
FROM
@Foo
GROUP BY
ID,
Val

-- Results
ID Val MyCount
----------- ----------- -----------
1 2 1
2 3 1
3 4 1
Go to Top of Page

kbrizendine
Starting Member

12 Posts

Posted - 2008-05-23 : 16:31:40
quote:
Originally posted by Lamprey

quote:
Originally posted by kbrizendine
Lol - I hope you're joking because otherwise you must think I'm an idiot.

I don't think your an idiot. I just don't think you understand the SQL you have posted.

If you examine your origial query you will see that you are grouping by two columns FESOR.REGION and FESOR.TYPE. So trying to get a COUNT using the OVER operater by PARTITIONING on FESOR.REGION and FESOR.TYPE will always result in a COUNT of 1.

So, again, I don't see why you need to use a COUNT since the value is always 1. Here is a sample of what happens:
DECLARE @Foo TABLE (ID INT, Val INT)

INSERT @Foo
SELECT 1, 2
UNION ALL SELECT 1, 2
UNION ALL SELECT 2, 3
UNION ALL SELECT 3, 4

SELECT
ID,
Val,
COUNT(*) OVER (PARTITION BY ID, Val) aS MyCount
FROM
@Foo
GROUP BY
ID,
Val

-- Results
ID Val MyCount
----------- ----------- -----------
1 2 1
2 3 1
3 4 1




Ok, I see your point but as I mentioned in my original post this is only one very simple example. My goal is not simply conversion of this SQL script such that I may be able to produce the same result set - it is to establish a methodology for converting ALL my SQL scripts that use PARTITION BY. So the fact that we may be able to use a trick to get the results I gave with the sample data I created only for testing doesn't help achieve my goal. But I can see now why you would not have realized that before now.
Go to Top of Page

kbrizendine
Starting Member

12 Posts

Posted - 2008-05-23 : 16:43:36
quote:
Originally posted by Peso

Why not? It produces the resultset you wanted.



E 12°55'05.25"
N 56°04'39.16"




Pedo,

I think I did provide everything needed to answer this question and I believe you gave the correct answer. As i posted above:

I've been looking into your suggestion and it seems like it is the only way EXCEPT that, unless I'm mistaken, I would need a unique key in order to implement a correlated subquery however these tables do not have unique keys. Do you agree with my conclusion that the only solution is to add a unique key to one or both tables?


Do you agree?
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2008-05-23 : 16:43:53
You can't establish a methodolgy for all PARTITION BY.
They can partition for other columns that you GROUP BY.

For example - ROW_NUMBER() OVER (PARTITION BY ..) can either be solved with

1) Correlated subquery
2) temp table with identity column

If you must make a generic solution, correlated subquery will do in most cases.



E 12°55'05.25"
N 56°04'39.16"
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2008-05-23 : 16:46:49
quote:
Originally posted by kbrizendine

Do you agree?

No. You can make correlated subqueries on composite keys too.



E 12°55'05.25"
N 56°04'39.16"
Go to Top of Page

Lamprey
Master Smack Fu Yak Hacker

4614 Posts

Posted - 2008-05-23 : 16:52:56
Do you have some more examples and maybe some sample data? Obviously the first sample query you showed can be simplified to remove the OVER clause. But, if there are other cases then let us know and maybe we can help come up with a generic solution for replacing the OVER clause for all of them.

Actualy, I'm more curious about why your COBOL compiler is complaining. Do you have some more detail on that? As I asked previously; is the dynamic sql?
Go to Top of Page

kbrizendine
Starting Member

12 Posts

Posted - 2008-05-23 : 17:57:02
quote:
Originally posted by Peso

quote:
Originally posted by kbrizendine

Do you agree?

No. You can make correlated subqueries on composite keys too.



E 12°55'05.25"
N 56°04'39.16"




Unfortunately there is no unique key whatsoever on FR.
Go to Top of Page
    Next Page

- Advertisement -