SQL triggers - conditionals and math operations - sql

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.

Related

Can you interleave multiple values when joining columns in OpenRefine?

I have a table of two columns where each cell has multiple values separated by a new-line. The values across the two columns are aligned. I would like to merge the values of the two columns in to a new column where the values of the first lines are merged before the values of the second line.
Something like this:
| Column 1 | Column 2 | New Column |
|----------|----------|------------|
|A |B |A (B) |
|C |D |C (D) |
|----------|----------|------------|
|E |F |E (F) |
|G |H |G (H) |
I tried both joining and adding a column based on values from columns but I can only merge in order so it ends up like this:
| Column 1 | Column 2 | New Column |
|----------|----------|------------|
|A |B |A |
|C |D |C |
| | |B |
| | |D |
|----------|----------|------------|
|E |F |E |
|G |H |G |
| | |F |
| | |H |
|----------|----------|------------|
I can get a manual individual answer like this:
cells["Column 1"].value.split("\n")[0] + " (" + cells["Column 2"].value.split("\n")[0] + ")"
Is there a way to iterate though the arrays? I have tried using forEach but only get errors.
You can use records and cell splitting for the required transformation:
Add new column "Index" via "Edit column => Add column based on this column..." and the GREL expression rowIndex. We need this column to restore the original rows after modifying them.
Move the new column "Index" to the beginning via "Edit column => Move column to beginning".
Change into records mode.
On "Column 1" split the cells on whitespace via "Edit column => Split multi-valued cells" using \n as separator and activating the "regular expression" checkbox.
Repeat the last step on "Column 2".
Add the new column using the expression row.cells["Column 1"].value + " (" + row.cells["Column 2"].value + ")"
Undo the cell splitting on via "Edit cells => Join multi-valued cells".
Note that if you use \n it will literally insert "\n" as separator.
So I usually use a custom separator like | and then replace it
with \n in a separate step.
Delete remaining columns (like "Index").

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;

How to merge columns of non unique rows in a database? (Sybase ASE)

Consider the data as:
|Column 1|Column 2|Column 3|
----------------------------
|A |Tom |1 |
|A |Tom |2 |
|B |Ron |3 |
There are few duplicates in Column 1 that are preventing me to create an index. I need to only create an index on Col 1.
How do I merge/flatten the values to get something like:
|Column 1|Column 2|Column 3|
----------------------------
|A |Tom |1,2 |
|B |Ron |3 |
How do we do this without using concatenate/LIST/STUFF? The database is Sybase ASE.
You'll have to write a loop to do this. But if you only want to create that index, why not create it as non-unique?
If you have to create it as unique, just add an identity column to the table and create the index on column1 + the identity column (or use the auto-identity DBoption)

How to Merge 2 Rows into one by comma separate?

I need to merge this individual rows to one column, I now how to merge column by comma separated,
+---------------+-------+-------+
|CID |Flag |Value |
+---------------+-------+-------+
|1 |F |10 |
|1 |N |20 |
|2 |F |12 |
|2 |N |23 |
|2 |F |14 |
|3 |N |21 |
|3 |N |22 |
+---------------+-------+-------+
Desired Result can be anything,
+-----------+----------------------------+ +--------------------------+
|Part Number| Value | | Value |
+-----------+----------------------------+ +--------------------------+
| 1 | 1|F|10 ; 1|N|20 | Or | 1|F|10 ; 1|N|20 |
| 2 | 2|F|12 ; 2|N|23 ; 2|F|14 | | 2|F|12 ; 2|N|23 ; 2|F|14 |
| 3 | 3|N|21 ; 3|N|22 | | 3|N|21 ; 3|N|22 |
+-----------+----------------------------+ +--------------------------+
Note:
Any hint in right direction with small example is more than enough
EDIT :
I have massive data in tables like thousands of records where parent's and child relationship is present. I have to dump this into text files by comma separated values In single line as record. Think as primary record has relationship with so many other table then all this record has to be printed as a big line.
And I am trying to achieve by creating query so load can be distributed on database and only thing i have to worry about in business is just dumping logic into text files or whatever form we need in future.
You can try to use LISTAGG and your query will look like this:
select a.cid, a.cid || listagg(a.flag || '|' || a.value, ',')
from foo.dat a
group by a.cid
You can use different separators and of course play with how the result will be formatted.

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