Retrieve data based on specified format - sql

I have a table with the configuration to
|Format|Value|Number
|%v-%n |A |1
|%v %n |B |2
|%v(%n)|C |3
|%v |D |4
|%n |E |5
|%v%%n |F |6
Using this configuration the result should be as follows (%v -> value %n - Number)
A-1
B 2
C(3)
D
5
F%6
I can do this using a case statement by including all known combinations like
CASE WHEN format = '%v-%n' THEN VALUE || '-' || NUMBER END
How can I make it generic to accept any combination rather than hardcoding things in a case statement?

So I tested this out with mysql:
SELECT REPLACE(REPLACE(format, '%v', value), '%n', number) from format;
I hope this helps!

Related

Conditional count of rows where at least one peer qualifies

Background
I'm a novice SQL user. Using PostgreSQL 13 on Windows 10 locally, I have a table t:
+--+---------+-------+
|id|treatment|outcome|
+--+---------+-------+
|a |1 |0 |
|a |1 |1 |
|b |0 |1 |
|c |1 |0 |
|c |0 |1 |
|c |1 |1 |
+--+---------+-------+
The Problem
I didn't explain myself well initially, so I've rewritten the goal.
Desired result:
+-----------------------+-----+
|ever treated |count|
+-----------------------+-----+
|0 |1 |
|1 |3 |
+-----------------------+-----+
First, identify id that have ever been treated. Being "ever treated" means having any row with treatment = 1.
Second, count rows with outcome = 1 for each of those two groups. From my original table, the ids who are "ever treated" have a total of 3 outcome = 1, and the "never treated", so to speak, have 1 `outcome = 1.
What I've tried
I can get much of the way there, I think, with something like this:
select treatment, count(outcome)
from t
group by treatment;
But that only gets me this result:
+---------+-----+
|treatment|count|
+---------+-----+
|0 |2 |
|1 |4 |
+---------+-----+
For the updated question:
SELECT ever_treated, sum(outcome_ct) AS count
FROM (
SELECT id
, max(treatment) AS ever_treated
, count(*) FILTER (WHERE outcome = 1) AS outcome_ct
FROM t
GROUP BY 1
) sub
GROUP BY 1;
ever_treated | count
--------------+-------
0 | 1
1 | 3
db<>fiddle here
Read:
For those who got no treatment at all (all treatment = 0), we see 1 x outcome = 1.
For those who got any treatment (at least one treatment = 1), we see 3 x outcome = 1.
Would be simpler and faster with proper boolean values instead of integer.
(Answer to updated question)
here is an easy to follow subquery logic that works with integer:
select subq.ever_treated, sum(subq.count) as count
from (select id, max(treatment) as ever_treated, count(*) as count
from t where outcome = 1
group by id) as subq
group by subq.ever_treated;

SQL triggers - conditionals and math operations

I have some database, lets say like that:
|a |b |c |d |e |
----------------------------------
|0 |12 |NA | | |
|NA|NA |30 | 42 | |
|NA|NA |NA | |53 |
I'd like to do few things:
for first row - set value to column D to be sin(b)
for second row - if the value is NA for column B, copy the previous known value (i.e (a,b)=(0,12))
on third row - if the value is NA for column B , copy the previous known value (i.e (a,b)=(0,12)) and set value to column D to be sin(b).
Those three examples of activities I have to execute on my databases for each row.
If triggers are not the right solution for this, I'd like to have recommendation how to solve it.

oracle group by using rank

TableOne
Id1| Level |Type|Survey Nr
--------------------------------
1| Level 1 |A |1
2| Level 2 |A |1
3| Level 3 |A |1
4| All Levels|A |1
-------------------------------
5| Level 1 |B |1
6| Level 2 |B |1
7| Level 4 |B |1
--------------------------------
8| Level 1 |A |2
9| Level 2 |A |2
10| Level 3 |A |2
11| All Levels|A |2
I want to group my data by type and survey Nr an the output of my query to be
1. All levels |A |1
2. Level 1 |B |1
3. Level 2 |B |1
4. Level 4 |B |1
5. All Levels |A |2
So when my subgroup Type/survey nr have level "All Levels" i will only display that record like in case A -1 and A2 else i want to display all records like in case B-1.
You can do this with the RANK() function and a CASE statement:
WITH cte AS (SELECT "Id1","Lev","Type","Survey_Nr"
,RANK() OVER (PARTITION BY "Type","Survey_Nr" ORDER BY CASE WHEN "Lev" = 'All Levels' THEN 0 ELSE 1 END) AS RN
FROM Table1)
SELECT *
FROM cte
WHERE RN = 1
ORDER BY "Id1"
Demo: SQL Fiddle
RANK() will assign a rank value to each set indicated in the PARTITION BY clause, and the CASE statement in the ORDER BY is used to set all values of Lev into one of two categories, giving preference to the "All Levels" values. Running this without the WHERE clause will help you see how the RANK() function is working.
I'd just UNION ALL the data where you have the string 'All Levels' to the data where it doesn't exist within that group. I've effectively assumed that your table is unique on LEVEL, TYPE and SURVEY_NR.
with base_data as (
select a
from the_table
)
select level, type, survey_nr
from base_data
where level = 'All Levels'
union all
select level, type, survey_nr
from base_data
where not exists ( select 1
from base_data
where level = 'All Levels'
and type = x.type
and survey_nr = x.survey_nr
)
Please note that LEVEL is normally an invalid name for a column; it's worth changing it.

Case to check if previous record matches last record

I have a query result like the one below. I wish to add a column in the query result that will flag as 1 if the [FinishTime] of the last record related to same [Machine] has the same [StartTime] as the current record.
So for example, in the table below, there is a flag=1 for row 5 ([Machine]=RD103) because it has the same start-time as for it's last record entry (row 3).
+---+-------+---------+-------+---------+----------------------+
|OID|Machine|StartTime|EndTime|DelayName|Consecutive Delay Flag|
+---+-------+---------+-------+---------+----------------------+
|1 |RD101 |20:00 |20:20 |A |0 |
+---+-------+---------+-------+---------+----------------------+
|2 |RD102 |21:00 |22:00 |A |0 |
+---+-------+---------+-------+---------+----------------------+
|3 |RD103 |23:00 |23:20 |B |0 |
+---+-------+---------+-------+---------+----------------------+
|4 |RD101 |20:20 |20:45 |C |1 |
+---+-------+---------+-------+---------+----------------------+
|5 |RD103 |23:20 |23:25 |A |1 |
+---+-------+---------+-------+---------+----------------------+
This is a great example of what analytic functions do - they don't force you to group your results (in other words - they still produce a single result per row), but you can have values that relate to other rows.
In your case, the LAG function should do the trick:
SELECT oid, machine, starttime, endtime, delayname,
CASE WHEN starttime =
LAG (starttime) OVER (PARTITION BY machine ORDER BY starttime)
THEN 1
ELSE 0
END AS flag
FROM my_table

Crystal Report SUM function with CASE

I have the following column values in my crystal report:
|Code |Unit |
|A |2 |
|B |3 |
|C |2 |
|D |3 |
|E |1 |
|F |1 |
|G |4 |
|H |(3) |
I want to summarize the Unit except the Units which has Code H,J,K, and L.
The Codes: H,J,K, and L contains units which has parenthesis.
Is there a way to do this?
If you want to exclude any row or value from summary, it can be done by writing your case inside Use a formula field under Evaluate in Running Total Field
Refer the following Image...
The rows or fields which doesn't satisfy the condition will be skipped from Evaluation of summary.
Try this and get back with results !!
If you want to omit only units with ‘(‘ in it just convert this filed to number
Use
Val ({Unit})
this will return 0 for non-numeric text and number for numeric create sum of these you will get what you want
If you want not to use any special then create formula field like this
if {fa_rep_vr_Main.CustomTitle} not in('A','B','C') then
0
else
val({Unit})
use sum of this
If you want sum of NewPriceAD then use it in mentained field