March 17, 2006 at 2:04 am
If my database table a is for example:
ColA ColB ColC
1 A NULL
2 B NULL
3 C 7
4 D NULL
5 E 6
6 F NULL
7 G 9
8 H NULL
9 J NULL
and my basic SQL is:
SELECT ColA, ColB
FROM dbo.a
WHERE ColA = 3;
can this be altered so that I get the output:
ColA ColB
3 C
3 G
3 J
i.e. for as long as ColC is not null it gets the record where the first found ColC is equal to ColA, but maintains the first found ColA value in the output.
Doug
March 17, 2006 at 3:36 am
so this is a hiarchy.
With SQL2005 you can use a CTE with a recursive part
With SQL2000 or SQL7 you'll have to build "recursivity" yourself.
e.g.
set nocount on
declare @Rows int,
@LevelNr int,
@TsRefresh datetime
--declare @Tables TABLE (
--TableName varchar(200),
--LevelID int)
set @TsRefresh = getdate()
--Primaire applicaties detecteren (Adam)
-- TRUNCATE TABLE --
DELETE FROM dbo.T_MenuItems_Explosion_WRK
set @LevelNr = 1
INSERT INTO dbo.T_MenuItems_Explosion_WRK (Main_Application_Id, Level_Nr, Menu_ID, Description_short, Description_Long, Rank, Menu_Action, Target, Parent_Menu_ID, Ts_Krea, User_Krea, Ts_Wijzig, User_Wijzig , Ts_Explosion ) --, User_Explosion)
SELECT p.Menu_ID, @LevelNr, p.Menu_ID, p.Description_short, p.Description_Long, p.Rank, p.Menu_Action, p.Target, p.Parent_Menu_ID, p.Ts_Krea, p.User_Krea, p.Ts_Wijzig, p.User_Wijzig , @TsRefresh
from T_MenuItems p
inner join
T_MenuItems A
on p.Parent_Menu_Id = A.Menu_Id
and a.Description_Short = 'Adam'
select @Rows = @@RowCount, @LevelNr = @LevelNr + 1
while @Rows > 1
begin
INSERT INTO dbo.T_MenuItems_Explosion_WRK (Main_Application_Id,Level_Nr, Menu_ID, Description_short, Description_Long, Rank, Menu_Action, Target, Parent_Menu_ID, Ts_Krea, User_Krea, Ts_Wijzig, User_Wijzig , Ts_Explosion ) --, User_Explosion)
SELECT e.Main_Application_Id, @LevelNr, I.Menu_ID, I.Description_short, I.Description_Long, I.Rank, I.Menu_Action, I.Target, I.Parent_Menu_ID, I.Ts_Krea, I.User_Krea, I.Ts_Wijzig, I.User_Wijzig , @TsRefresh
from T_MenuItems I
inner join T_MenuItems_Explosion_WRK E
on e.Level_Nr = @LevelNr - 1
and i.Parent_Menu_ID = E.Menu_Id
select @Rows = @@RowCount, @LevelNr = @LevelNr + 1
Print '-- level ' + str(@LevelNr - 1 ) + ' / ' + str(@Rows)
end
delete from T_MenuItems_Explosion
set nocount off
Insert into T_MenuItems_Explosion
select *
from T_MenuItems_Explosion_WRK
order by Main_Application_Id, parent_menu_id, Level_Nr, rank
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data/code to get the best help[/url]
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
March 17, 2006 at 5:22 am
Hi all,
Just to appy alzdba's example to your situation, Doug...
--This SQL script is safe to run
declare @t table (ColA int, ColB varchar(1), ColC int)
insert @t
select 1, 'A', NULL
union all select 2, 'B', NULL
union all select 3, 'C', 7
union all select 4, 'D', NULL
union all select 5, 'E', 6
union all select 6, 'F', NULL
union all select 7, 'G', 9
union all select 8, 'H', NULL
union all select 9, 'J', NULL
declare @Root int
set @Root = 3
declare @U table (level int, ColA int, ColB varchar(1), ColC int)
insert into @U select 1, ColA, ColB, ColC from @t where ColA = @Root
declare @level int
set @level = 2
while not exists (select * from @U where ColC is null)
begin
insert into @U
select @level, ColA, ColB, ColC from @t
where ColA in (select ColC from @U where level = @level - 1)
set @level = @level + 1
end
select @Root as ColA, ColB from @U order by level
Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
March 17, 2006 at 5:46 am
I'm stuck with SQL7 at the moment, so many thanks for all your help.
Much appreciated.
Doug
March 17, 2006 at 5:54 am
just for the record, to tease a bit
SQL2005 way:
start with RyanRandall 's example ...
;
with MyCTE
as (
select @level as MyLevel, ColA, ColB, ColC
from @t
where ColA = @Root
UNION ALL
select @level, A.ColA, A.ColB, A.ColC
from @t A
inner JOIN MyCTE B
on A.ColA = B.ColC
)
--select *
select @Root as ColA, ColB
from MyCTE
go
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data/code to get the best help[/url]
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
March 17, 2006 at 6:24 am
Wow! that's really neat. Since this is a fairly new project I'm certainly considering moving it up to SQL2005. Is there a cheap developer edition I can get to play around with and show my people how much better it would be?
Doug
March 17, 2006 at 6:32 am
maybe you'll find it overhere :
http://www.microsoft.com/sql/prodinfo/features/default.mspx
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data/code to get the best help[/url]
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
March 19, 2006 at 1:30 am
Thanks for that. I'm trying to find out locally how to get a copy as I don't live in the States.
Hope you don't mind if I ask another question.
In your example, you built the table as part of the T-SQL, but in reality a much more complex table exists in my database which I need to get and then manipulate as you have shown and then output the data in a similar format to that shown.
If I select the data I need, how do I then access the data returned by the select?
For example:
Select ColA, ColB, ColC
From tableA
Where tableID in (listOfIDsRequestedByUser);
Now how do I get the value of say ColC in row 2 of the result set?
And if I do it by setting the select equal to some variable e.g. @resultset nvarchar(n), how do I know what size to set n as the result set could be any size at some unknown time in the future and then is the value I want equal to @resultset.ColC[2] or what?
Doug
March 20, 2006 at 12:41 am
So your TableA is dynamic ?
if not, write a query to perform your select, determine a maximum occurences for listOfIDsRequestedByUser and just build and inlist that supports it;
or build a #tempTb containing the tableID's you parsed from the inputparameter containing the id's.
this parsing can be done like this :
I copied this partial from http://www.sqlservercentral.com/scripts/contributions/592.asp
declare @tableIDList varchar(4000),
@Delimiter varchar(10)
-- for test
select @tableIDList = 'A,B,C', @Delimiter=','
--
create table #tblSplit
(ItemId int IDENTITY(1, 1) NOT NULL PRIMARY KEY,
Item varchar(4000) NULL)
DECLARE @Delimiter2 varchar(12),
@item varchar(4000),
@iPos int,
@DelimWidth int
--had to do this cuz if they send in a > 9 char delimiter I could not pre and post append the % wildcards
SET @Delimiter2 = @Delimiter
SET @Delimiter2 = ISNULL(@Delimiter2, ',')
SET @DelimWidth = LEN(@Delimiter2)
IF RIGHT(RTRIM(@tableIDList), 1) <> @Delimiter2
SELECT @tableIDList = RTRIM(@tableIDList) + @Delimiter2
IF LEFT(@Delimiter2, 1) <> '%'
SET @Delimiter2 = '%' + @Delimiter2
IF RIGHT(@Delimiter2, 1) <> '%'
SET @Delimiter2 = @Delimiter2 + '%'
SELECT @iPos = PATINDEX(@Delimiter2, @tableIDList)
WHILE @iPos > 0
BEGIN
SELECT @item = LTRIM(RTRIM(LEFT(@tableIDList, @iPos - 1)))
IF @@ERROR <> 0 BREAK
SELECT @tableIDList = RIGHT(@tableIDList, LEN(@tableIDList) - (LEN(@item) + @DelimWidth))
IF @@ERROR <> 0 BREAK
INSERT INTO #tblSplit VALUES(@item)
IF @@ERROR <> 0 BREAK
SELECT @iPos = PATINDEX(@Delimiter2, @tableIDList)
IF @@ERROR <> 0 BREAK
END
select * from #tblSplit
Then you can join with #tblSplit
To get the value of colc in your result at row 2, you could
select @Root as ColA, colc , ColB from @U order by level, @Root, colc
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data/code to get the best help[/url]
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
March 20, 2006 at 12:55 am
I really do thank you so much for all your help, but since I don't quite understand your last reply I think I may have misled you again in waht I'm trying to do.
This is what I actually need to do:
Get all rows from db tables a and b (with join) where a.ColA (PK) matches any in list of ColA's and other conditions.
Loop through rows {
--Add row to new table variable.
--While ColC in last added row not equal null {
----Get row from db table a where ColA = lastAddedRow.ColC
----Add data from table b and ColA from table a in lastAddedRow to new data from table a except ColA
----Add this new row to table variable
--}
}
Select table variable for output.
Now I've had a go at writing this and I get the error 'incorrect syntax near table'.
My code as follows:
SET NOCOUNT ON
DECLARE @TaxID int,
@PriceID int,
@Inclusive bit,
@ShowWithItem bit,
@ShowWithTotal bit,
@TaxName nvarchar(30),
@TaxRate smallmoney,
@TaxStart smalldatetime,
@TaxEnd smalldatetime,
@ReplacedBy int,
@lastReplacedBy int,
@t table (TaxID int, PriceID int, Inclusive bit, ShowWithItem bit, ShowWithTotal bit, TaxName nvarchar(30), TaxRate smallmoney, TaxStart smalldatetime, TaxEnd smalldatetime, ReplacedBy int)
DECLARE cTax CURSOR LOCAL FAST_FORWARD
FOR
SELECT Taxes.TaxID, PriceID, Inclusive, ShowWithItem, ShowWithTotal, TaxName, TaxRate, TaxStart, TaxEnd, ReplacedBy
FROM Taxes, TaxesApplied
WHERE //conditions
OPEN cTax
FETCH NEXT FROM cTax INTO @TaxID, @PriceID, @Inclusive, @ShowWithItem, @ShowWithTotal, @TaxName, @TaxRate, @TaxStart, @TaxEnd, @ReplacedBy
INSERT INTO @t (TaxID, PriceID, Inclusive, ShowWithItem, ShowWithTotal, TaxName, TaxRate, TaxStart, TaxEnd, ReplacedBy) VALUES (@TaxID, @PriceID, @Inclusive, @ShowWithItem, @ShowWithTotal, @TaxName, @TaxRate, @TaxStart, @TaxEnd, @ReplacedBy)
WHILE @@Fetch_Status = 0
BEGIN
WHILE @ReplacedBy NULL
SET @lastReplacedBy = @ReplacedBy
BEGIN
SELECT @TaxName = TaxName, @TaxRate = TaxRate, @TaxStart = TaxStart, @TaxEnd = TaxEnd, @ReplacedBy = ReplacedBy
FROM Taxes
WHERE TaxID = @lastReplacedBy
INSERT INTO @t (TaxID, PriceID, Inclusive, ShowWithItem, ShowWithTotal, TaxName, TaxRate, TaxStart, TaxEnd, ReplacedBy) VALUES (@TaxID, @PriceID, @Inclusive, @ShowWithItem, @ShowWithTotal, @TaxName, @TaxRate, @TaxStart, @TaxEnd, @ReplacedBy)
END
FETCH NEXT FROM cTax INTO @TaxID, @PriceID, @Inclusive, @ShowWithItem, @ShowWithTotal, @TaxName, @TaxRate, @TaxStart, @TaxEnd, @ReplacedBy
END
CLOSE cTax
DEALLOCATE cTAX
SELECT * FROM @t
SET NOCOUNT OFF;
Doug
March 20, 2006 at 1:41 am
With SQL7 you will have to use a #tempTB in stead of a declare @tb table !
It does not know tablevariables !
If you are only interested in the last replacementId, I would first select the keys for the Baserows (where ColA = yyy)
then build an explosion list for these keys using the loop techneque.
Remember to put your First ColA in the explosionlist so you can select RootColA, max(replacementid)
from #tmpExplosion
group by RootColA
Lets hope you've got a better way than max(id) to determine the most recent (e;g; a datetime or so).
I hope this gets you on track
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data/code to get the best help[/url]
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
March 20, 2006 at 7:08 pm
Thanks so much for all your help.
The table variable and a few other minor bugs were the last errors to cure and now my very first piece of T-SQL works perfectly!!
Thanks again,
Doug
March 21, 2006 at 1:25 am
FYI
check out http://www.microsoft.com/sql/downloads/trial-software.mspx
for an 180-days trial version.
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data/code to get the best help[/url]
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
March 21, 2006 at 1:41 am
I called Microsoft's local office and they've put me in touch with their distributor who sells it for $55, just a little more that the US price. So I should have it installed in about 2 days time. Can't wait !!
When I've got it I'll try out your newer method !!
Thanks again,
Doug
Viewing 14 posts - 1 through 13 (of 13 total)
You must be logged in to reply to this topic. Login to reply