I've got a Cube with one measure, which uses COUNT as aggregation function.
The result of MDX queries looks something like this:
| Germany | USA | Russia | France | Italy |
------------------------------------------------------
2010 | 15 | 20 | null | null | null |
2011 | 20 | 25 | 10 | null | null |
2012 | 25 | 30 | 15 | 5 | null |
2010 - 2012| 60 | 75 | 25 | 5 | null |
For me it works just fine, but our customer wants the whole aggreagtion result to be null if one of the dimension elements is null.
So the result has to look like this:
| Germany | USA | Russia | France | Italy |
------------------------------------------------------
2010 | 15 | 20 | null | null | null |
2011 | 20 | 25 | 10 | null | null |
2012 | 25 | 30 | 15 | 5 | null |
2010 - 2012| 60 | 75 | null | null | null |
And to make things more complicated this behavior should be the same, when the time dimension is put on the slice axis.
So the Result for the following MDX query
SELECT [Area].[Germany]:[Area].[Italy] on 0
FROM ExampleCube
WHERE ([Year].[2010]:[Year].[2012])
should look like this
| Germany | USA | Russia | France | Italy |
------------------------------------------------------
| 60 | 75 | null | null | null |
Exists a way in SSAS and/or MDX to achieve this behavior?
Related
I have a JSON column containing col_values for another table. I want to return rows from that other table for each item in the JSON object.
If this was an INT column, I would use JOIN, but I need to JOIN every entry in the JSON object.
Take:
writers :
| id | name | projects (JSON) |
|:-- |:-----|:------------------|
| 1 | Andy | ["1","2","3","4"] |
| 2 | Hank | ["3","4","5","6"] |
| 3 | Alex | ["1","7","8","9"] |
| 4 | Joe | ["1","5","6","7"] |
| 5 | Ken | ["2","4","5","6"] |
| 6 | Zach | ["2","7","8","9"] |
| 7 | Walt | ["2","5","6","7"] |
| 8 | Mike | ["2","3","4","5"] |
cities :
| id | name | project |
|:-- |:---------|:--------|
| 1 | Boston | 1 |
| 2 | Chicago | 2 |
| 3 | Cisco | 3 |
| 4 | Seattle | 4 |
| 5 | North | 5 |
| 6 | West | 6 |
| 7 | Miami | 7 |
| 8 | York | 8 |
| 9 | Tainan | 9 |
| 10 | Seoul | 1 |
| 11 | South | 2 |
| 12 | Tokyo | 3 |
| 13 | Carlisle | 4 |
| 14 | Fugging | 5 |
| 15 | Turkey | 6 |
| 16 | Paris | 7 |
| 17 | Midguard | 8 |
| 18 | Fugging | 9 |
| 19 | Madrid | 1 |
| 20 | Salvador | 2 |
| 21 | Everett | 3 |
I need every city ordered by name for Mike (id=8).
Desired results:
This is what I'm getting and what I need to get (ORDER BY name).
Output :
| id | name | project |
|:---|:---------|:--------|
| 13 | Carlisle | 4 |
| 2 | Chicago | 2 |
| 3 | Cisco | 3 |
| 21 | Everett | 3 |
| 14 | Fugging | 5 |
| 5 | North | 5 |
| 20 | Salvador | 2 |
| 4 | Seattle | 4 |
| 11 | South | 2 |
| 12 | Tokyo | 3 |
Current query, but this can't be the best way...
SQL >
SELECT c.*
FROM cities c
WHERE EXISTS (
SELECT 1
FROM writers w
WHERE JSON_CONTAINS(
w.projects, CONCAT('\"', c.project, '\"'))
AND w.id = '8'
)
ORDER BY c.name;
DB Fiddle with the above. Is there a better way to do this "properly"?
Background
If it matters, I need to keep using JSON as the datatype because my server-side software that uses this database normally reads that column best if presented as a JSON object.
I would normally just do several database calls and iterate through that JSON object in my server-side language, but that is way too expensive with so many database calls, notwithstanding that it is even more costly to do multiple database calls for pagination.
I need all the results in a single database call. So, I need to JOIN or otherwise loop through each item in the JSON object within SQL.
Start with JOIN
Per a comment from a user, there is a better way...
SQL >
SELECT c.*
FROM writers w
JOIN cities c ON JSON_CONTAINS(w.projects, CONCAT('\"', c.project, '\"'))
WHERE w.id = '8'
ORDER BY c.name;
Output is the same...
Output :
id
name
project
13
Carlisle
4
2
Chicago
2
3
Cisco
3
21
Everett
3
14
Fugging
5
5
North
5
20
Salvador
2
4
Seattle
4
11
South
2
12
Tokyo
3
DB Fiddle
I have a specific requirement to pivot up two columns, one numeric and one string. I am well versed with SQL pivot, however, could not reach a solution for this.
My raw data is like:
Country | Segment | Year | Parameter_Name | Parameter_Value_Numeric | Parameter_Value_String
USA | 1 | 2003 | Datapoint1 | 100 | null
USA | 1 | 2003 | Datapoint2 | 148 | null
USA | 1 | 2003 | Datapoint3 | null | Upper values(s)
USA | 2 | 2003 | Datapoint1 | 121 | null
USA | 2 | 2003 | Datapoint2 | 180 | null
USA | 2 | 2003 | Datapoint3 | null | Medium values(s)
The results I want is something like:
Country | Segment | Year | Datapoint1 | Datapoint2 | Datapoint3
USA | 1 | 2003 | 100 | 148 | Upper values(s)
USA | 2 | 2003 | 121 | 180 | Medium values(s)
The issue being faced is that Datapoint1 & Datapoint2 are float and Datapoint3 is nvarchar. Hence, pivot is able to use only one of these.
You can try this below logic-
DEMO HERE
SELECT Country,Segment,Year,
MAX(CASE WHEN Parameter_Name = 'Datapoint1' THEN Parameter_Value_Numeric END) Datapoint1,
MAX(CASE WHEN Parameter_Name = 'Datapoint2' THEN Parameter_Value_Numeric END) Datapoint2,
MAX(CASE WHEN Parameter_Name = 'Datapoint3' THEN Parameter_Value_String END) Datapoint3
FROM your_table
GROUP BY Country,Segment,Year
I have written some code to merge two tables together. The values that are displayed are null.
+----------+--------------+-----------------------------------------------+-------------+----------+----------+------+----------+
| Movie_ID | Release_year | Movie_Title | Duration | Genre_ID | Actor_ID | Role | Movie_ID |
+----------+--------------+-----------------------------------------------+-------------+----------+----------+------+----------+
| 10001 | 1997 | Titantic | 190 minutes | 40001 | NULL | NULL | NULL |
| 10002 | 1998 | Shakesphere in Love | 123 minutes | 40002 | NULL | NULL | NULL |
| 10003 | 1999 | American Beauty | 122 minutes | 40003 | NULL | NULL | NULL |
| 10004 | 2000 | Gladiator | 155 minutes | 40004 | NULL | NULL | NULL |
| 10005 | 2001 | A beautiful Mind | 135 minutes | 40004 | NULL | NULL | NULL |
| 10006 | 2002 | Chicago | 113 minutes | 40005 | NULL | NULL | NULL |
| 10007 | 2003 | The Lord of the Rings: The return of the King | 201 minutes | 40006 | NULL | NULL | NULL |
| 10008 | 2004 | Million Dollar Baby | 132 minutes | 40007 | NULL | NULL | NULL |
| 10009 | 2005 | Crash | 112 minutes | 40008 | NULL | NULL | NULL |
| 10010 | 2006 | The Departed | 151 minutes | 40009 | NULL | NULL | NULL |
| 10011 | 2007 | No Country for Old Men | 122 minutes | 40009 | NULL | NULL | NULL |
| 10012 | 2008 | Slumdog Millionaire | 120 minutes | 40008 | NULL | NULL | NULL |
| 10013 | 2009 | The Hurt Locker | 131 minutes | 40009 | NULL | NULL | NULL |
| 10014 | 2010 | The King\s speech | 118 minutes | 40010 | NULL | NULL | NULL |
| 10015 | 2011 | The Artist | 100 minutes | 40011 | NULL | NULL | NULL |
| 10016 | 2012 | Argo | 120 minutes | 40012 | NULL | NULL | NULL |
| 10017 | 2013 | 12 Years a Slave | 134 minutes | 40004 | NULL | NULL | NULL |
| 10018 | 2014 | Birdman or The Unexpected Virtue of Ignorance | 119 minutes | 40003 | NULL | NULL | NULL |
| 10019 | 2015 | Spotlight | 129 minutes | 40008 | NULL | NULL | NULL |
| 10020 | 2016 | Moonlight | 111 minutes | 40013 | NULL | NULL | NULL |
| 10021 | 2017 | The Shape of Water | 123 minutes | 40012 | NULL | NULL | NULL |
| 10022 | 2018 | Green Book | 130 minutes | 40011 | NULL | NULL | NULL |
+----------+--------------+-----------------------------------------------+-------------+----------+----------+------+----------+
SELECT *
FROM databaseoscars.movie a
LEFT JOIN databaseoscars.`movie cast` b ON a.Movie_ID = b.Actor_ID;
I expected the output to be all data is displayed on one table.
Your problem is here: a.Movie_ID = b.Actor_ID. A movie will never be an actor. Use your movie cast table's movie ID instead:
SELECT *
FROM databaseoscars.movie m
LEFT JOIN databaseoscars.`movie cast` mc ON mc.movie_id = m.movie_id;
In MySQL and MariaDB, you could also use the USING clause:
SELECT *
FROM databaseoscars.movie m
LEFT JOIN databaseoscars.`movie cast` mc USING (movie_id);
I have the following columns in table Sales :
Category1,priceA,priceB,Category2,costA,costB,type.(some items in category1 are same as category2)
sum(priceA), sum(priceB)
are to be grouped by category1,type.
sum(costA), sum(costB)
are to be grouped by category2,type.
I need the final output as
Union(category1,category2) as category3 ,sum(priceA)+sum(costA),sum(priceB)+sum(costB),type
to be grouped by UNION(category1+category2),type.
(sum(priceA)+sum(costA) would happen whenever items in category1 matches with category2 and same would be for sum(priceB)+sum(costB))
I tried to do it by
select category1,sum(priceA),sum(priceB),type group by category1,type
UNION ALL
select category2,sum(costA),sum(costB),type group by category2,type
Then following it up with another sum and group by. But I want to know how to do it without separately selecting and avoiding the union of basically 2 tables. Can I use group by followed by case statement here? Actually the table I referred as sales is an inner join of multiple tables , hence the motivation to not use select on it separately on two occasaions( in my actual case it would be union of 4 select queries on the table which makes the query look really big too). Plus I dont have permission to create procedure so no PL/SQL. Any fancy way for the above situation which will shorten the query and improve the performance ?
EDIT- SAMPLE DATA (Category1,PriceA,PriceB,Category2,CostA,CostB,Type)
+-----+----+----+-----+----+----+---+
| AUS | 20 | 25 | UK | 35 | 40 | X |
| UK | 30 | 26 | SA | 32 | 40 | Y |
| USA | 22 | 24 | NZ | 38 | 36 | Z |
| BRA | 16 | 10 | USA | 25 | 25 | Z |
| RUS | 20 | 15 | UK | 20 | 30 | X |
+-----+----+----+-----+----+----+---+
Which I divided into union of two tables as these:
+-----+----+----+---+
| AUS | 20 | 25 | X |
| UK | 30 | 26 | Y |
| USA | 22 | 24 | Z |
| BRA | 16 | 10 | Z |
| RUS | 20 | 15 | X |
+-----+----+----+---+
And
+-----+----+----+---+
| UK | 55 | 70 | X |
| SA | 33 | 40 | Y |
| NZ | 38 | 36 | Z |
| USA | 25 | 25 | Z |
+-----+----+----+---+
Final output would be like :
+-----+----+----+---+
| UK | 55 | 70 | X |
| UK | 30 | 26 | Y |
| NZ | 38 | 36 | Z |
| USA | 47 | 49 | Z |
| AUS | 20 | 25 | X |
| SA | 32 | 40 | Y |
| BRA | 16 | 10 | Z |
| RUS | 20 | 15 | X |
+-----+----+----+---+
This will give you what you want. SQLFiddle.
with sample_data1 as (
select "Category1", "PriceA", "PriceB", "Type"
from sample_data
union all
select "Category2", "CostA", "CostB", "Type"
from sample_data
)
select "Category1", sum("PriceA"), sum("PriceB")
from sample_data1 sd1
group by "Category1", "Type"
You will have to have a union at some point, because you need to increase the number of rows from your original source table. You can't do it with just a CASE.
Ok, so i'm trying to write a complex query (at least complex to me) and need some pro help. This is my database setup:
Table: MakeList
| MakeListId | Make |
| 1 | Acura |
| 2 | Chevy |
| 3 | Pontiac |
| 4 | Scion |
| 5 | Toyota |
Table: CustomerMake
| CustomerMakeId | CustomerId | _Descriptor |
| 1 | 123 | Acura |
| 2 | 124 | Chevy |
| 3 | 125 | Pontiac |
| 4 | 126 | Scion |
| 5 | 127 | Toyota |
| 6 | 128 | Acura |
| 7 | 129 | Chevy |
| 8 | 130 | Pontiac |
| 9 | 131 | Scion |
| 10 | 132 | Toyota |
Table: Customer
| CustomerId | StatusId |
| 123 | 1 |
| 124 | 1 |
| 125 | 1 |
| 126 | 2 |
| 127 | 1 |
| 128 | 1 |
| 129 | 2 |
| 130 | 1 |
| 131 | 1 |
| 132 | 1 |
What i am trying to end up with is this...
Desired Result Set:
| Make | CustomerId|
| Acura | 123 |
| Chevy | 124 |
| Pontiac | 125 |
| Scion | 131 |
| Toyota | 127 |
I am wanting a list of unique Makes with one active (StatusId = 1) CustomerId to go with it. I'm assuming i'll have to do some GROUP BYs and JOINS but i haven't been able to figure it out. Any help would be greatly appreciated. Let me know if i haven't given enough info for my question. Thanks!
UPDATE: The script doesn't have to be performant - it will be used one time for testing purposes.
Something like this:
select cm._Descriptor,
min(cu.customerid)
from CustomerMake cm
join Customer cu on cuo.CustomerId = cm.CustomerId and cu.StatusId = 1
group by cm._Descriptor
I left out the MakeList table as it seems unnecessary because you are storing the full make name as _Descriptorin the CustomerMake table anyway (so the question is what is the MakeList table for? Why don't you store a FK to it in the CustomerMake table?)
You want to
(a) join the customer and customermake tables
(b) filter on customer.statusid
(c) group by customermake._descriptor
Depending on your RDBMS, you may need to explicitly apply a group function to customer.customerid to include it in the select list. Since you don't care which particular customerid is displayed, you could use MIN or MAX to just pick an essentially arbitrary value.