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!

2 KOMENTARZE

  1. 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

  2. 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.