SQLite split column on another column's value - sql

I have a database in which multiple variables appear as consecutive rows (shown below, variables differentiated by their tags). As a result, their values appear as consecutive rows in the 'value' column.
Existing table:
For data analysis, I need to split each variable's value into separate columns, as illustrated below.
The SQLite query is listed below. I have tried using GROUP BY tag and averaging the values, but the result becomes too granular to be useful.
Advice would be much appreciated!
SELECT
tag
,time
,value
FROM
[archive]..[interp]
WHERE
tag
IN
( 'flow1.Val'
, 'flow2.Val'
, 'density1.Val'
, 'density2.Val'
)
AND
time
BETWEEN
't-1d' and 't'
AND
timestep = '1h'

You can use conditional aggregation:
select time,
max(case when tag = 'flow1.Val' then value end) as flow1_val,
max(case when tag = 'flow2.Val' then value end) as flow2_val,
max(case when tag = 'density1.Val' then value end) as density1_val,
max(case when tag = 'density2.Val' then value end) as density2_val
from [archive]..[interp]
group by time
Depending on your actual requirement, you might want to use another aggregate function than max(), it you have more than one row for a given time/tag tuple.

Related

Subtract values from one column based on values in another (TSQL)

I have table where I need to subtract values in one column based on conditions applied to the other. For example, I want to subtract values with code fst and trd, meaning (12 - 23).
I don't want to declare separate variables. Is it possible to make this with a query?
One method is conditional aggregation:
select sum(case when code = 'fst' then value else - value end)
from t
where code in ('fst', 'trd');
Assuming you have only one row for each code, you can also use a join:
select tf.value - tt.value
from t tf join
t tt
on tf.code = 'fst' and tt.code = 'trd'

Conditional COUNT within CASE statement

Table 1, is a list of clients, what membership they have, what service they used, and the date the service was used
Table 2, is just table 1 grouped by month and membership type, then a count of the service sessions
What I am trying to do is count membership sessions only by particular service types. This is what I have so far, it returns an error saying 'Service_Type' is not in an aggregate function or group by clause, when I put 'Service_Type' in a group by, the query has no errors but the SESSIONS column is all NULL.
SELECT
DATEFROMPARTS(YEAR(t1.Date),MONTH(t1.Date),1)AS 'Draft_Date',
Membership,
CASE
WHEN Membership = 5 AND Service_Type = 'A' THEN COUNT(*)
WHEN Membership = 2 AND Service_Type IN ('J','C')
END AS'SESSIONS'
FROM Table1 t1
GROUP BY DATEFROMPARTS(YEAR(t1.Date),MONTH(t1.Date),1),Membership
The case statement will include all memberships and service types but I think this is enough for my example. Any help would be greatly appreciated! I've been on this for days.
Table 1
Table 2
You were nearly there! I've made a few changes:
SELECT
DATEFROMPARTS(YEAR(t1.Date), MONTH(t1.Date),1) AS Draft_Date,
Membership,
COUNT(CASE WHEN t1.Membership = 5 AND t1.Service_Type = 'A' THEN 1 END) as m5stA,
COUNT(CASE WHEN t1.Membership = 2 AND t1.Service_Type IN ('J','C') THEN 1 END) as m2stJC
FROM Table1 t1
GROUP BY YEAR(t1.Date), MONTH(t1.Date), Membership
Changes:
Avoid using apostrophes to alias column names, use ascii standard " double quotes if you must
When doing a conditional count, put the count outside the CASE WHEN, and have the case when return something (any non null thing will be fine - i used 1, but it could also have been 'x' etc) when the condition is met. Don't put an ELSE - CASE WHEN will return null if there is no ELSE and the condition is not met, and nulls don't COUNT (you could also write ELSE NULL, though it's redundant)
Qualify all your column names, always - this helps keep the query working when more tables are added in future, or even if new columns with the same names are added to existing tables
You forgot a THEN in the second WHEN
You don't necessarily need to GROUP BY the output of DATEFROMPARTS. When a deterministic function is used (always produces the same output from the same inputs) the db is smart enough to know that grouping on the inputs is also fine
Your example data didn't contain any data that would make the COUNT count 1+ by the way, but I'm sure you will have other conditional counts that work out (it just made it harder to test)
use sum
SELECT DATEFROMPARTS(YEAR(t1.Date),MONTH(t1.Date),1) AS Draft_Date , Membership,
sum(CASE WHEN Membership = 5 AND Service_Type = 'A' THEN 1 else 0 end),
sum(case WHEN Membership = 2 AND Service_Type IN ('J','C') then 1 else 0 end)
FROM Table1 t1 group by DATEFROMPARTS(YEAR(t1.Date),MONTH(t1.Date),1)

SSRS grouping chart by parameter

I have problem with grouping by parameter in my chart.
Let's assume query that gives data like below:
I would like to Group category in the cart based on parameter.
Parameter has value City or Country but it can be also different (no possibility to define constant list)
On the chart I should see (based on parameter):
Parameter: City
Parameter: Country
Is there any possibility to do it in SSRS?
Assuming your parameter has values of 0 and 1 where 0=Country and 1=City....
You just need to set the following items
The cell to be displayed ( in column 1 in your example)
The Group On expression of your row group
The Sort by expression of your row group
to the same expression, something like this...
=IIF(Parameters!groupColumn.Value =0, Fields!country.Value, Fields!city.Value)
Its the exact same expression in all three places.
If you can't get this working, let me know and I'll post an example but it's pretty simple.
You can do use an expression for group by:
select (case when parameter = 'City' then city
when parameter = 'Country' then country
end) as which,
sum(value)
from t
group by (case when parameter = 'City' then city
when parameter = 'Country' then country
end);
That said, I think you should have separate queries in SSRS for the different values. Such parameterized queries are harder to optimize and harder to maintain.

How to sum in SQL with conditions?

It's more than likely this question has already been asked before and that I could just not find it now knowing for what to search.
Assuming I have a simple table with two columns, one column holding one of two values, e.g. "positive" and "negative", and the other holding an integer.
Is there a way using standard SQL to calculate a sum of all the numbers in the second column whereby the number is added if the field in the first column reads "positive" and vice-versa subtracted for "negative" numbers?
Also, it would be interesting to understand how to do the same with MS Access if it is different from standard SQL.
You case use sum(case):
select sum(case when col1 = '+' then value
when col2 = '-' then - value
end) as overall
from t;
In MS Access, you would use switch or iff
select sum(switch(col1 = '+', value, col2 = '-', - value, 0)
) as overall
from t;

SSRS CountRows of a specific Field containing a specific Value

I am building an SSRS report. I have a DataSet that contains several Fields, one of which is Doc_Type. Doc_Type can contain several values, one of which is 'Shipment'.
In my report, I want to count the number of Doc_Types that are equal to 'Shipment'. This is what I am using, and it is not working:
=CountRows(Fields!Doc_Type.Value = "Shipments")
The error I get is: "The Value expression for the textrun 'Doc_Type.Paragraphs[0].TextRuns[0]' has a scope parameter that is not valid for an aggregate function. The scope parameter must be set to a string constant that is equal to either the name of a containing group, the name of a containing data region, or the name of a dataset.
You need to use an IIF to evaluate your fields and SUM the results. If your expression is in a table, you could use this:
=SUM(IIF(Fields!Doc_Type.Value = "Shipments", 1, 0))
There are many ways to achieve this.
Method 1
You can set up your expression something like this
=SUM(IIf(Fields!Doc_Type.Value = "Shipments", 1, 0), "YourDataSetName")
Remember SSRS is case sensitive so put your dataset name and Field names correctly.
Method 2
I prefer handling it in SQL as I want to keep the business logic out of RDLs.
You can use window functions to get the shipment count.
Also notice in the case of count I haven't added ELSE 0 condition. Because that will give wrong results. Count doesn't care what is the value inside it. It just counts all Non Null values. ELSE NULL will work.
SELECT Column1, Column2, Column3,
SUM(CASE WHEN Doc_Type = 'Shipments' THEN 1 ELSE 0 END) OVER() ShipmentCount_UsingSum
COUNT(CASE WHEN Doc_Type = 'Shipments' THEN 1 END) OVER() ShipmentCount_UsingCount
FROM myTable
JOIN....
WHERE .....
Now you can use this field in the report.