Малко помощ диря....
14 отговора
523 прегледа
Малко помощ диря....
щото нещо зациклих и съвсем изключих....
Та ....имам две таблици
1. Registry
ID | Name | FName |
-------------------------------
3076 Иван Иванов
PK = ID
2.Таблица Moves
ID | Year |
----------------------
3076 2003
3076 2002
3076 2001
PK = ID, Year ; FK=ID
С queryто ми получавам резултат:
3076, Иван, Иванов, 2003
3076, Иван, Иванов, 2002
3076, Иван, Иванов, 2001
А аз искам резултат от вида:
3076, Иван, Иванов, 2003,2002,2001
Та ....имам две таблици
1. Registry
ID | Name | FName |
-------------------------------
3076 Иван Иванов
PK = ID
2.Таблица Moves
ID | Year |
----------------------
3076 2003
3076 2002
3076 2001
PK = ID, Year ; FK=ID
С queryто ми получавам резултат:
3076, Иван, Иванов, 2003
3076, Иван, Иванов, 2002
3076, Иван, Иванов, 2001
А аз искам резултат от вида:
3076, Иван, Иванов, 2003,2002,2001
Re: Малко помощ диря....
Ами най накратко само със SQL може да се напише с много лефт джойнове, ама става грозно. Затова курсор, цикъл ...
Re: Малко помощ диря....
И как точно ти изглежда query-то?
So long and thanks for all the fish!

So long and thanks for all the fish!
Re: Малко помощ диря....
тц.
ще ми се да е с query, без курсор...тъпото е, че изтъпях тотално...
пробвах и със select case, ама мойто циклене си продължава.......... и пак достигам до резултата, който не ми върши работа...
затова иде реч за помощ....
ще ми се да е с query, без курсор...тъпото е, че изтъпях тотално...
пробвах и със select case, ама мойто циклене си продължава.......... и пак достигам до резултата, който не ми върши работа...
затова иде реч за помощ....
Re: Малко помощ диря....
е то е ясно как...
въпросът ми е как да го докарам то резултатът, който искам или другото решение на проблема ми е от properties - Report builder - или на Repeating frame, или на field, но там четох хелпове и до никъде не стигнах.
въпросът ми е как да го докарам то резултатът, който искам или другото решение на проблема ми е от properties - Report builder - или на Repeating frame, или на field, но там четох хелпове и до никъде не стигнах.
Re: Малко помощ диря....
Абе куирито е сайдинска работа и е доста чийтване:
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Moves]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Moves]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Registry]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Registry]
GO
CREATE TABLE [dbo].[Moves] (
[ID] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Yr] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
GO
INSERT [Moves]([ID],[Yr]) VALUES('3076','2003')
INSERT [Moves]([ID],[Yr]) VALUES('3076','2002')
INSERT [Moves]([ID],[Yr]) VALUES('3076','2001')
INSERT [Moves]([ID],[Yr]) VALUES('3077','2000')
INSERT [Moves]([ID],[Yr]) VALUES('3077','2002')
CREATE TABLE [dbo].[Registry] (
[ID] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Name] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[FName] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
GO
INSERT [Registry]([ID],[Name],[FName]) VALUES('3076','John','Doe')
INSERT [Registry]([ID],[Name],[FName]) VALUES('3077','Tim','Smith')
SELECT R.*, M1.Yr, M2.Yr, M3.Yr
FROM Registry AS R
LEFT OUTER JOIN Moves AS M1 ON
R.ID = M1.ID
AND M1.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M1.ID)
LEFT OUTER JOIN Moves AS M2 ON
R.ID = M2.ID
AND M2.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M2.ID AND Yr NOT IN (M1.Yr))
LEFT OUTER JOIN Moves AS M3 ON
R.ID = M3.ID
AND M3.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M3.ID AND Yr NOT IN (M1.Yr, M2.Yr))
Което дава:
ID Name FName Yr Yr Yr
---- ---- ----- ---- ---- ----
3076 John Doe 2003 2002 2001
3077 Tim Smith 2002 2000 NULL
Разбира се това с допускането че Moves има комплексен ключ (ID, Yr).
Представете си колко ме мързи да работя та седнах да напиша това.
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Moves]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Moves]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Registry]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Registry]
GO
CREATE TABLE [dbo].[Moves] (
[ID] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Yr] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
GO
INSERT [Moves]([ID],[Yr]) VALUES('3076','2003')
INSERT [Moves]([ID],[Yr]) VALUES('3076','2002')
INSERT [Moves]([ID],[Yr]) VALUES('3076','2001')
INSERT [Moves]([ID],[Yr]) VALUES('3077','2000')
INSERT [Moves]([ID],[Yr]) VALUES('3077','2002')
CREATE TABLE [dbo].[Registry] (
[ID] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Name] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[FName] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
GO
INSERT [Registry]([ID],[Name],[FName]) VALUES('3076','John','Doe')
INSERT [Registry]([ID],[Name],[FName]) VALUES('3077','Tim','Smith')
SELECT R.*, M1.Yr, M2.Yr, M3.Yr
FROM Registry AS R
LEFT OUTER JOIN Moves AS M1 ON
R.ID = M1.ID
AND M1.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M1.ID)
LEFT OUTER JOIN Moves AS M2 ON
R.ID = M2.ID
AND M2.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M2.ID AND Yr NOT IN (M1.Yr))
LEFT OUTER JOIN Moves AS M3 ON
R.ID = M3.ID
AND M3.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M3.ID AND Yr NOT IN (M1.Yr, M2.Yr))
Което дава:
ID Name FName Yr Yr Yr
---- ---- ----- ---- ---- ----
3076 John Doe 2003 2002 2001
3077 Tim Smith 2002 2000 NULL
Разбира се това с допускането че Moves има комплексен ключ (ID, Yr).
Представете си колко ме мързи да работя та седнах да напиша това.
Re: Малко помощ диря....
Ех, Перине, Перине и тез жлъти очи...
не ми върши работа решението ти с дроп и инсерт и криейт тейбъл.. Нали се сещаш, че и двете таблици са доста по-сложни и имат сумати др. фк, които в случая не са съществени... (напр. ФК към таблицата дето записвам кой на коя дата, коя разписка и т.н си е платил даденото задължение. ) За всяка година за всеки ид има по един запис.
не ми върши работа решението ти с дроп и инсерт и криейт тейбъл.. Нали се сещаш, че и двете таблици са доста по-сложни и имат сумати др. фк, които в случая не са съществени... (напр. ФК към таблицата дето записвам кой на коя дата, коя разписка и т.н си е платил даденото задължение. ) За всяка година за всеки ид има по един запис.
Re: Малко помощ диря....
Той Перина добре го е написал.
Ти гледай селекта. Другото е само скрипт за тестване
Кофтито е, че така става само ако предварително знаеш колко години ще имаш в един ред (max).
Иначе пътя "зациклих" е верния, но без "съвсем изключих"
Ти гледай селекта. Другото е само скрипт за тестване
Кофтито е, че така става само ако предварително знаеш колко години ще имаш в един ред (max).
Иначе пътя "зациклих" е верния, но без "съвсем изключих"
Re: Малко помощ диря....
Кажи каква е базата поне?
И това "2003,2002,2001" в отделни колони ли го искаш, или като низ в една колона? Ако искаш да е в отделни, без динамичен SQL няма да минеш. Ако е като низ в една, може да се направи нещо по въпроса.
И това "2003,2002,2001" в отделни колони ли го искаш, или като низ в една колона? Ако искаш да е в отделни, без динамичен SQL няма да минеш. Ако е като низ в една, може да се направи нещо по въпроса.
Re: Малко помощ диря....
ако кажеш че ти трябва за MySQL веднага мога да ти дам 2 решения за проблема
Re: Малко помощ диря....
Значи самото решение е само това:
SELECT R.*, M1.Yr, M2.Yr, M3.Yr
FROM Registry AS R
LEFT OUTER JOIN Moves AS M1 ON
R.ID = M1.ID
AND M1.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M1.ID)
LEFT OUTER JOIN Moves AS M2 ON
R.ID = M2.ID
AND M2.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M2.ID AND Yr NOT IN (M1.Yr))
LEFT OUTER JOIN Moves AS M3 ON
R.ID = M3.ID
AND M3.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M3.ID AND Yr NOT IN (M1.Yr, M2.Yr))
Другото е само за тестване. Не съм имал предвид че трябва да се изпълнява всеки път, нито че това трябва да е конкретната структура на таблиците.
БТВ с много лефт джойнове трябва да се внимава каква ще е производителността. Специално за SQL Server трябва да се напише като:
LEFT OUTER MERGE JOIN
иначе междинните резултати могат лесно да станат по няколко милиона реда.
Много поздрави на Амирлин
, да и кажеш че не съм забравил че имам да я черпя едно кафе.
SELECT R.*, M1.Yr, M2.Yr, M3.Yr
FROM Registry AS R
LEFT OUTER JOIN Moves AS M1 ON
R.ID = M1.ID
AND M1.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M1.ID)
LEFT OUTER JOIN Moves AS M2 ON
R.ID = M2.ID
AND M2.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M2.ID AND Yr NOT IN (M1.Yr))
LEFT OUTER JOIN Moves AS M3 ON
R.ID = M3.ID
AND M3.Yr IN (SELECT MAX (Yr) FROM Moves WHERE ID = M3.ID AND Yr NOT IN (M1.Yr, M2.Yr))
Другото е само за тестване. Не съм имал предвид че трябва да се изпълнява всеки път, нито че това трябва да е конкретната структура на таблиците.
БТВ с много лефт джойнове трябва да се внимава каква ще е производителността. Специално за SQL Server трябва да се напише като:
LEFT OUTER MERGE JOIN
иначе междинните резултати могат лесно да станат по няколко милиона реда.
Много поздрави на Амирлин
Re: Малко помощ диря....
То реално погледнато даже с курсор да е, ако SQL-a не е динамичен няма как да върнеш променлив брой колони.
Мен друго ме притеснява в такъв род решения - масовото използване на леви джойнове може да доведе до катастрофално ниска производителност. Различните бази се опитват да оптимизират, ама обикновенно не се справят добре.
Курсорите по принцип са зло (и до колкото знам и на SQL Server и на Oracle) водят до създаване на темп таблица, но в случая мисля че са по-малкото зло.
Също и динамичен SQL си трябва да може да се определи верния брой колони.
Мен друго ме притеснява в такъв род решения - масовото използване на леви джойнове може да доведе до катастрофално ниска производителност. Различните бази се опитват да оптимизират, ама обикновенно не се справят добре.
Курсорите по принцип са зло (и до колкото знам и на SQL Server и на Oracle) водят до създаване на темп таблица, но в случая мисля че са по-малкото зло.
Също и динамичен SQL си трябва да може да се определи верния брой колони.
Re: Малко помощ диря....
IMHO, ако става въпрос за сложен анализ (OLAP) най добре е това да става на клиента, като необходимите данни се извличат от сървъра с прости селекти.
Ако е въпрос само за показване бих го направил (FB1.5) на сървъра в stored procedure, която да върне във varchar списъка на годините с някакъв разделител. В този случай няма да ми се наложи даже да правя динамичен SQL.
Ако е въпрос само за показване бих го направил (FB1.5) на сървъра в stored procedure, която да върне във varchar списъка на годините с някакъв разделител. В този случай няма да ми се наложи даже да правя динамичен SQL.
CREATE PROCEDURE LIST_OF_YEARS
RETURNS (
ID INTEGER,
NAME VARCHAR(50),
FNAME VARCHAR(50),
YEARS VARCHAR(1024))
AS
DECLARE VARIABLE YR VARCHAR(1024);
begin
for select ID,Name,FName
from registry
into :id, :name,:fname
do begin
Years='';
for select Yr
from moves
where ID=:id
order by YR
into :YR
do Years=:years||:YR||',';
suspend;
end
end
Re: Малко помощ диря....
> ако става въпрос за сложен анализ (OLAP) най добре е това да
> става на клиента, като необходимите данни се извличат от
> сървъра с прости селекти.
Не ми се ще да давам съвети без да знам изскванията, ама съм 99% сигурен че Year би било едно от измеренията. Съответно OLAP клиента ще работи с него като с всяко друго измерение, включително ще може да подрежда различните стойности на измерението по колони вместо редове.
> става на клиента, като необходимите данни се извличат от
> сървъра с прости селекти.
Не ми се ще да давам съвети без да знам изскванията, ама съм 99% сигурен че Year би било едно от измеренията. Съответно OLAP клиента ще работи с него като с всяко друго измерение, включително ще може да подрежда различните стойности на измерението по колони вместо редове.