SSAS Tabular: Append two tables with a different number of columns - ssas

I'd like to ´UNION´ or ´Append´ two tables in SSAS with certain overlapping Column names, and some differences as well, which changes over time.
TableA:
| ColA | ColB | ColC | ColD |
|------|------|------|------|
| 1 | 1 | 0 | 1 |
| 0 | 1 | 1 | 1 |
TableB:
| ColA | ColB | ColE |
|------|------|------|
| 1 | 1 | 0 |
| 0 | 1 | 1 |
Expected Result:
| ColA | ColB | ColC | ColD | ColE |
|------|------|------|------|------|
| 1 | 1 | 0 | 1 | |
| 0 | 1 | 1 | 1 | |
| 1 | 1 | | | 0 |
| 0 | 1 | | | 1 |
Is there an option in SSAS to make this happen?
Kind regards,
Igor

The easiest way is to use the Append function in Power Query. See https://learn.microsoft.com/en-us/power-query/append-queries
In M, it is a Table.Combine. See https://learn.microsoft.com/en-us/powerquery-m/table-combine

Related

TSQL - Number groups based on distinct values in certain columns

Let's say I have a table like this:
| ID | ColA | ColB | ColC | ... |
|-----|------|------|------|-----|
| 1 | 111 | XXX | foo | |
| 1 | 111 | XXX | bar | |
| ... | ... | ... | ... | |
| 1 | 111 | YYY | foo | |
| 1 | 111 | YYY | bar | |
| ... | ... | ... | ... | |
| 1 | 999 | XXX | foo | |
| 1 | 999 | XXX | bar | |
| ... | ... | ... | ... | |
| 1 | 999 | YYY | foo | |
| 1 | 999 | YYY | bar | |
| ... | ... | ... | ... | |
| 2 | 111 | XXX | foo | |
| 2 | 111 | XXX | bar | |
| ... | ... | ... | ... | |
There are further columns to the right with all sorts of other values.
I want to partition this table in T-SQL into distinct groups only by columns "ID", "ColA" and "ColB", without regard to all other columns. Then I want to sequentially number those groups. My final result should look like this:
| ID | ColA | ColB | ColC | ... | GroupNumber |
|-----|------|------|------|-----|-------------|
| 1 | 111 | XXX | foo | | 1 |
| 1 | 111 | XXX | bar | | 1 |
| ... | ... | ... | ... | | ... |
| 1 | 111 | YYY | foo | | 2 |
| 1 | 111 | YYY | bar | | 2 |
| ... | ... | ... | ... | | ... |
| 1 | 999 | XXX | foo | | 3 |
| 1 | 999 | XXX | bar | | 3 |
| ... | ... | ... | ... | | ... |
| 1 | 999 | YYY | foo | | 4 |
| 1 | 999 | YYY | bar | | 4 |
| ... | ... | ... | ... | | ... |
| 2 | 111 | XXX | foo | | 5 |
| 2 | 111 | XXX | bar | | 5 |
| ... | ... | ... | ... | | ... |
It seems like this should be an easy problem but I struggle to get a handle on it. I have a certain suspicion that this should work somehow with DENSE_RANK and the partitioning clause in that function. My approach is:
SELECT
*,
DENSE_RANK() OVER(
PARTITION BY ID, ColA, ColB
ORDER BY ColC
) AS GroupNumber
FROM my_table
but this keeps increasing the GroupNumber within each one of these blocks as well.
If I'm understanding what you're looking for, you have the right idea, however you don't need to partition the data within the ranking function - you're looking for the rank of the combination of columns Id, ColA, and ColB within the entire dataset, not the rank of records within those combination of columns.
If that's the case, you simply would remove your partition clause in your dense_rank(), like this:
SELECT
*,
DENSE_RANK() OVER(ORDER BY ID, ColA, ColB) AS GroupNumber
FROM my_table
That assumes that you aren't trying to assign group #'s in any specific order other than the order of ID, ColA, and ColB, which I think is what you want, however you also used an "ORDER BY ColC" clause in your original example - I'm guessing you did that because you need to add an order by clause to a ranking function.
If you are however trying to order the groups a different way, would need to know that and would require something a little different.

Create results grid from database tables: SQL

I have a table which describes patients' medical symptoms which has the following structure.
Note that patient 1 and patient 2 have two symptoms.
| patientID | symptomName | SymptomStartDate | SymptomDuration |
|-----------|----------------|------------------|-----------------|
| 1 | Fever | 01/01/2020 | 10 |
| 1 | Cough | 02/01/2020 | 5 |
| 2 | ChestPain | 03/01/2020 | 6 |
| 2 | DryEyes | 04/01/2020 | 8 |
| 3 | SoreThroat | 05/01/2020 | 2 |
| 4 | AnotherSymptom | 06/01/2020 | 1 |
Using this data, I want to create a grid showing which symptoms each patient had, in the following format (with 1 indicating that the patient had that symptom and 0 indicating that the patient did not have that symptom)
| patientID | Fever | Cough | ChestPain | DryEyes | SoreThroat | AnotherSymptom |Headache|
|-----------|-------|-------|-----------|---------|------------|----------------|--------|
| 1 | 1 | 1 | 0 | 0 | 0 | 0 |0 |
| 2 | 0 | 0 | 1 | 1 | 0 | 0 |0 |
| 3 | 0 | 0 | 0 | 0 | 1 | 0 |0 |
| 4 | 0 | 0 | 0 | 0 | 0 | 1 |0 |
Note that none of the patients in this first table have headache but table 2 does have a column for headache filled with 0s. I have a list of all symptoms I want to include as columns in a separate table. (let's call that table symptom: The symptom table has only two columns : symptomName and symptomID)
Use a crosstab query:
TRANSFORM
Count(Symptoms.SymptomStartDate)
SELECT
Symptoms.PatientID
FROM
Symptoms
GROUP BY
Symptoms.PatientID
PIVOT
Symptoms.SymptomName
IN ('Fever','Cough','ChestPain','DryEyes','SoreThroat','AnotherSymptom','Headache');
Apply this format to the Format property of field SymptomStartDate:
0;;;0
Output:

SQL: Ranking Sections separately of a Rollup over multiple columns

I try to do a Rollup over multiple columns and then apply a ranking on each stage/section of the rollup process. The result should look somewhat like the following:
| ColA | ColB | ColC | RankingCriteria | Ranking |
|------|------|------|-----------------|---------|
| - | - | - | 10 | 1 |
|------|------|------|-----------------|---------|
| A | - | - | 10 | 1 |
| B | - | - | 8 | 2 |
|------|------|------|-----------------|---------|
| A | a | - | 9 | 1 |
| A | b | - | 7 | 2 |
| A | c | - | 5 | 3 |
| A | d | - | 2 | 4 |
|------|------|------|-----------------|---------|
| B | a | - | 8 | 1 |
| B | c | - | 7 | 2 |
| B | b | - | 2 | 3 |
|------|------|------|-----------------|---------|
| A | a | x | 7 | 1 |
| A | a | y | 5 | 2 |
| A | a | z | 4 | 3 |
|------|------|------|-----------------|---------|
| A | b | y | 6 | 1 |
|------|------|------|-----------------|---------|
| A | c | w | 10 | 1 |
| A | c | y | 10 | 1 |
| A | c | z | 8 | 2 |
| A | c | x | 6 | 3 |
|------|------|------|-----------------|---------|
| A | d | y | 4 | 1 |
|------|------|------|-----------------|---------|
| B | a | w | 10 | 1 |
| B | a | x | 8 | 2 |
|------|------|------|-----------------|---------|
| B | b | y | 6 | 1 |
| B | b | z | 5 | 2 |
| B | b | w | 4 | 3 |
|------|------|------|-----------------|---------|
| B | c | x | 6 | 1 |
|------|------|------|-----------------|---------|
So as you can see each grouping set has it's own ranking.
The basic Rollup-Query for this is simple but the ranking is giving me headaches and I am running out of ideas on how to achieve this.
Select ColA, ColB, ColC, RankingCriteria
From table
Group By Rollup(ColA, ColB, ColC)
The problem is that I cannot use a normal Rank() over (Partition by ...) because there is no partition I could use that'd work on the whole thing.
I think this will produce what you want:
SELECT r.*,
row_number() over (partition by (case when colb is null and colc is null and cola is not null
then 1 else 0 end),
(case when colb is null and colc is null and cola is not null
then NULL else A end),
(case when colb is null and colc is null and cola is not null
then NULL else B end)
order by RankingCriteria desc) as seqnum
FROM (Select ColA, ColB, ColC, RankingCriteria
From table
Group By Rollup(ColA, ColB, ColC)
) r;
The way I read the logic is that partitioning by A and B works for all but the second group. That is why this uses the three case statements.

Ask about query in sql server

i have table like this:
| ID | id_number | a | b |
| 1 | 1 | 0 | 215 |
| 2 | 2 | 28 | 8952 |
| 3 | 3 | 10 | 2000 |
| 4 | 1 | 0 | 215 |
| 5 | 1 | 0 |10000 |
| 6 | 3 | 10 | 5000 |
| 7 | 2 | 3 |90933 |
I want to sum a*b where id_number is same, what the query to get all value for every id_number? for example the result is like this :
| ID | id_number | result |
| 1 | 1 | 0 |
| 2 | 2 | 523455 |
| 3 | 3 | 70000 |
This is a simple aggregation query:
select id_number, sum(a*b)
from t
group by id_number
I'm not sure what the first column is for.

Ordering by min value in result, while respecting grouping in mysql

Second question in two days on this same sort of topic.
I currently am using the following query:
SELECT name,suite,webpagetest.id,MIN(priority) AS min_pri
FROM webpagetest,comparefileerrors
WHERE vco="aof" AND user="1" AND calibreversion="9"
AND webpagetest.id=comparefileerrors.id
AND comparefileerrors.priority IS NOT NULL
GROUP BY id,suite
ORDER BY COALESCE(suite,name),min_pri
ASC ;
This gives me results that look as follows:
+-----------------------------+-----------------------------+-------+---------+
| name | suite | id | min_pri |
+-----------------------------+-----------------------------+-------+---------+
| bz1273_cmdline_execplussvdb | NULL | 6203 | 2 |
| bz1508_SEGV_password | NULL | 6185 | 2 |
| bz1747_bad_lvsf | NULL | 36683 | 1 |
| set_get_status | shortsRepairDB_2009.1_suite | 6193 | 0 |
| u2uDemo | shortsRepairDB_2009.1_suite | 6195 | 0 |
| change_sets | shortsRepairDB_2009.1_suite | 6194 | 0 |
| add_delete_mask_polygon | shortsRepairDB_2009.1_suite | 6191 | 0 |
| isolate_shorts | shortsRepairDB_2009.1_suite | 6196 | 0 |
| add_delete_text | shortsRepairDB_2009.1_suite | 6197 | 0 |
| assign_short_AND_user_info | shortsRepairDB_2009.1_suite | 6198 | 2 |
| comment_short | shortsRepairDB_2009.1_suite | 6192 | 2 |
+-----------------------------+-----------------------------+-------+---------+
However, what I would like to do is order them by the minimum priority that is encountered in suite, if there is one. Suite is an optional field, and if it is null, then there is no need to do this grouping. I want to use the minimum value in the suite determine the overall placement of the suite.
I am heavily considering redesigning my app to use PHP to do this sorting, but for the mean time, it would be nice to do this with mysql.
The results should look like the following:
+-----------------------------+-----------------------------+-------+---------+
| name | suite | id | min_pri |
+-----------------------------+-----------------------------+-------+---------+
| set_get_status | shortsRepairDB_2009.1_suite | 6193 | 0 |
| u2uDemo | shortsRepairDB_2009.1_suite | 6195 | 0 |
| change_sets | shortsRepairDB_2009.1_suite | 6194 | 0 |
| add_delete_mask_polygon | shortsRepairDB_2009.1_suite | 6191 | 0 |
| isolate_shorts | shortsRepairDB_2009.1_suite | 6196 | 0 |
| add_delete_text | shortsRepairDB_2009.1_suite | 6197 | 0 |
| assign_short_AND_user_info | shortsRepairDB_2009.1_suite | 6198 | 2 |
| comment_short | shortsRepairDB_2009.1_suite | 6192 | 2 |
| bz1747_bad_lvsf | NULL | 36683 | 1 |
| bz1273_cmdline_execplussvdb | NULL | 6203 | 2 |
| bz1508_SEGV_password | NULL | 6185 | 2 |
+-----------------------------+-----------------------------+-------+---------+
You can add the lowest priority for a suite as a column. Assuming the suite is in webpagetest and the priority in comparefileerrors, something like:
SELECT name,suite,webpagetest.id, MIN(priority) AS min_pri,
(select min(wt2.priority)
from webpagetest wt2
inner join comparefileerrors cfe2
on wt2.id = cfe2.id
where wt2.suite = wt.suite) as suite_min_pri
FROM webpagetest wt, comparefileerrors cfe
And then use that in the order by:
ORDER BY COALESCE(suite,name), suite_min_pri
If you have values for priority in the range [0,9], you can add another column for combined priority, and let that value be 10 * (if suite exists ? 1 : 0) + priority
SELECT
name,suite,webpagetest.id,MIN(priority) AS min_pri
(CASE WHEN suite IS NOT NULL THEN 1 ELSE 0 END)*10+priority as combined_pri
FROM webpagetest,comparefileerrors
WHERE vco="aof" AND user="1" AND calibreversion="9"
AND webpagetest.id=comparefileerrors.id
AND comparefileerrors.priority IS NOT NULL
GROUP BY id,suite
ORDER BY COALESCE(suite,name),combined_pri
ASC ;
if the priority is in a larger set of numbers, just increase the multiplier. The key is to have it be one digit larger than the biggest value of priority.