Siedzę właśnie nad jednym z projektów i natrafiłem na dziwną rzecz, której nie jestem wstanie wytłumaczyć i szukam rozwiązania. Może będziecie wstanie pomóc.
Sprawa rozbija się o zapytanie MDX do cube. Nie jestem odpowiedzialny za tworzenie i zarządzanie cubes, więc jedynie co robię to pobieram dane z nich.
Zapytanie zostało zmienione pod względem hierarchii, wymiarów i cubes – w sensie nazwy zostały zmienione
Teraz, jeżeli wykonam zapytanie w SQL Managment Studio:
SELECT {} ON COLUMNS, CROSSJOIN( [Dim].[AttrHierarchyName].[AttrNameName], [Dim].[AttrHierarchyType].[AttrNameType] ) ON ROWS FROM [Cube] WHERE { [Dim].[AttrHierarchyCode].&[WHATEVER] }
To dostanę zero rekordów – co jest poprawnym zachowaniem.
Jeżeli przeniosę zapytanie do C#:
var cmd = con.CreateCommand(); cmd.CommandText = @" SELECT {} ON COLUMNS, CROSSJOIN( [Dim].[AttrHierarchyName].[AttrNameName], [Dim].[AttrHierarchyType].[AttrNameType] ) ON ROWS FROM [Cube] WHERE { [Dim].[AttrHierarchyCode].&[WHATEVER] }"; var cellSet = cmd.ExecuteCellSet(); var rows = cellSet.Axes[1].Set.Tuples; // count == 0
To też dostanę zero rekordów. I ok, to jest jasne. Wartości WHATEVER nie ma i tak się powinno zachować zapytanie.
Jeżeli jednak wprowadzę zmienną do zapytania i całość będzie miała taką oto postać:
var cmd = con.CreateCommand(); cmd.CommandText = @" SELECT {} ON COLUMNS, CROSSJOIN( [Dim].[AttrHierarchyName].[AttrNameName], [Dim].[AttrHierarchyType].[AttrNameType] ) ON ROWS FROM [Cube] WHERE { StrToMember(@MyCode, CONSTRAINED) }"; cmd.Parameters("MyCode", "[Dim].[AttrHierarchyCode].&[{0}]".FormatWith("WHATEVER")); var cellSet = cmd.ExecuteCellSet(); var rows = cellSet.Axes[1].Set.Tuples; // count == 331, why???
To zostanie mi zwrócone ponad 300 rekordów – dokładnie tyle ile by zostało zwróconych gdyby WHERE
nie był brany pod uwagę.
Wiem, że mogę dodać do StrToMemeber
flagę CONSTRAINED
, która spowoduje, że przy wywołaniu polecenia, dostanę exception
. Ale tego nie chcę, chcę by to się zachowało tak jak przy normalnym zapytaniu.
Czy jest taka możliwość? Czy to, że dostaje tyle rekordów to problem z cubes? Czy po prostu MDX tak ma i live with it.
Jeżeli nie będzie innego wyjścia to zawszę mogę dodać flagę i wyłapać exception, jednak wolałbym tego uniknąć.
Z góry dzięki za pomoc!
Hej, u mnie wszystko działa ;)
Z Twoim kodem i zapytaniem jednak coś mi się nie zgadza. Po pierwsze dlaczego nie zwracasz żadnej miary, tylko same atrybuty? W tym momencie zwracasz same nazwy par atrybutów, które występują w kostce dla odpowiedniego przecięcia konkretnych hierarchii. Zwracasz je bez żadnych faktycznych wyników liczbowych i dodatkowo zwracasz wszystkie możliwe kombinacje, a nie te, które faktycznie wystąpiły. To znaczy gdybyś dodał jakąś miarę, na przykład wartość sprzedaży to zobaczyłbyś wszystkie możliwe kombinacje niezależnie od tego czy w danej kombinacji odbyła się jakaś sprzedaż – zobaczyłbyś na przecięciach również NULLe.
Według mnie zapytanie MDX powinno wyglądać tak:
SELECT {[Measures].[Miara1]} ON COLUMNS,
NONEMPTY(
CROSSJOIN(
[NazwaWymiar1].[NazwaHierarchia1].[NazwaAtrybut1].members,
[NazwaWymiar2].[NazwaHierarchia1].[NazwaAtrybut1]..members
)
) ON ROWS
FROM [Kostka]
WHERE {[NazwaWymiar3].[NazwaHierarchia1].[NazwaAtrybut1].&[Wartosc1Atrybut1]}
Dodatkowo, jeżeli chodzi o kod C#, to o ile się nie mylę to do Twojego polecenia w ogóle nie poszedł parametr (aczkolwiek nie jestem w stu procentach pewien)
U mnie takie, normalnie dodanie parametru działa:
string WhereClouse = “[NazwaWymiar].[NazwaHierarchi].[NazwaAtrybutu].&[WartoscAtrybutu]”;
AdomdParameter param = new AdomdParameter(“MyCode”, WhereClouse);
cmd.Parameters.Add(param);
Dla powyższego kodu i powyższego zapytania jeżeli podam prawidłową wartość atrybutu to dostaję zestaw danych, jeżeli bazie nie ma konkretnej wartości atrybutu lub po prostu nie ma danych dla konkretnego przecięcia kostki to dostają 0 rekordów w wyniku.
Cały kod, który na szybko napisałem dla kostki AdventureWorks:
http://nopaste.info/03ac8bae00.html
Pozdrawiam,
Sławek
dzieki Sławek za odpowiedz.
Jednak to nie rozwiazuje problemu. Juz tlumacze.
Po pierwsze, jezeli chodzi o to co pobieram – tak zwracam jedynie same atrybuty i tylko to mnie interesuje. Tak zostl cube stworzony. Potrzebuje tych atrybutow by wygenerowac odpowiednie zapytania do pobrania dalej danych i by stworzyc linki do innych stron ktore uszczegolniaja pewne dane.
Po drugie, to z parametrami, to w C# jest to jedno i to samo: `Add(string, object)` tworzy wewnetrznie `AdomdParameter`. Ale sprawdzilem czy moze to nie jest bug, nie, all jest ok.
Po trzecie i to jest chyba najwazniejsze. Twoje zapytanie zwraca wyniki – miary. Dlatego tez mozesz zastosowac `NON EMPTY` na `ROWS`. Ja tego nie moge zrobic, bo wtedy zawsze dostane 0 wynikow i nigdy nie otrzymam atrybutow.
No chyba, ze obejsciem bedzie zwrocenie dummy measure ktory do niczego mi nie jest potrzebny. Jednak takie zapytanie powoduje, ze nic nie dostaje spowrotem – zarowno dla poprawnego `CODE` jak i dummy one :(
Comments are closed.