SQL conditional extraction - sql

I need a SQL query which allow me to extract the current value of a column if this column has not be modified since the add of the object.
Or the last before the current value if the column was modified.
Note that the current value is saved in a table A and the history of modification in table B
Table A
ID
STATUS
other columns ....
Table B
ID
items_ID (which is the ID of element in table A)
modif_ID (indicate which column was modified)
old_value
new_value
other columns..
Thanks in advance,
Imene.
For exemple, For table A
id STATUS Title Description User
1 Closed Help Need help for configuring Apache IBH
2 Solved DSL DSL is down IBH
3 Assign Hardware Need new network cards IBH
For table B
id Items_id Modif_id Date_mod Old_value New value
1 1 1 12-02-2014 Assign solved
2 1 1 15-02-2014 solved closed
3 3 1 20-02-2014 New Assign
3 3 4 21-02-2014 hard Hardware
All modif where the modif_id!=1 are ignored.
For each element id (Table A), we extract the current status if the status dosen’t change or the last before the current value if the status is changed one or more time. The expected result is:
id STATUS
1 solved
2 solved
3 New

Related

Count duplicates in an internal table?

I just want to ask on how to count duplicates in an internal table. I wanted to this in order for me to count per customer and put it into the Customer count column.
Sales Employee Customer Customer Count
a 1 2
a 2 2
b 3 3
b 2 3
b 4 3
c 1 1
as suncatcher mentions in his comment, using sql aggregates is more efficient than looping through internal tables. But if that is not possible in your case, one way would be to use the collect statement. collect adds entries to an internal table and adds up numerical fields when a row with the same key fields already exists. Create an internal table with a field for your sales employee, another field for the count and loop through your sales table, using collect to update your count table for each sale.
types: begin of t_count,
employee type text10,
count type i,
end of t_count.
data: it_count type standard table of t_count,
wa_count type t_count.
loop at it_sales into wa_sales.
move: wa_sales-employee to wa_count-employee,
1 to wa_count-count.
collect wa_count into it_count.
endloop.
The example assumes you have a table it_sales, a work area wa_sales, both with a field employee. Table it_count then contains a list of your employees (in the order they appear in your sales table) and the number of times they appeared in the sales table.
FIELD-SYMBOLS : <lfs_sales> TYPE ty_sales.
Assuming li_sales is an internal table with columns Sales_employee, Customer and customer_count. Initially the table entries are present as follows.
Sales_employee Customer customer_count
a 1 0
a 2 0
b 3 0
b 2 0
b 4 0
c 1 0
We need to calculate the duplicate sales_employee count and update the customer_count field. We can make use of collect statement as suggested by Dirik or make use of control break statements as shown below.
Prerequisite to make use of SUM keyword is to initialize the customer_count as 1 in each row so that it can sum up the customer count based on similar sales_employee.
LOOP AT li_sales ASSIGNING <lfs_sales>.
<lfs_sales>-customer_count = 1.
ENDLOOP.
Now the entries look as shown below.
Sales_employee Customer customer_count
a 1 1
a 2 1
b 3 1
b 2 1
b 4 1
c 1 1
Following code does update the customer_count field value.
LOOP AT li_sales INTO rec_sales.
AT END OF employee.
SUM.
MOVE-CORRESPONDING rec_sales TO rec_count.
APPEND rec_count TO li_count.
CLEAR rec_count.
ENDAT.
ENDLOOP.
SORT li_count BY employee.
LOOP AT li_sales ASSIGNING <lfs_sales>.
CLEAR rec_count.
READ TABLE li_count INTO rec_count
WITH KEY employee = <lfs_sales>-employee
BINARY SEARCH.
IF sy-subrc IS INITIAL.
<lfs_sales>-count = rec_count-count.
ENDIF.
ENDLOOP.
Now the internal table gets assigned with customer_count as below.
Sales_employee Customer customer_count
a 1 2
a 2 2
b 3 3
b 2 3
b 4 3
c 1 1

Decrement all values in a column after insert at top SQL

Before Inserting
Id Priority
1 . 1
2 . 2
3 . 3
After Inserting Id: 4, Priority 2
Id Priority
1 . 1
4 . 2
2 . 3
3 . 4
fairly new to postgres, and i have a table with a column named priority. this column should have unique values, and if you attempt to give a row a priority that already exists, it would basically insert it with that priority, and decrement all the priorities that are <= by one to accommodate it.
is there a term for this sort of behavior? i know it will involve a column with unique values, but are there any model constraints i can introduce to enable this sort of behavior? or do i need to manually code an algorithm to do this and account for all edge cases.
I wouldn't store priority as it's own field. Create the table as ID, priority, Date_entered. Then use:
Select ID, rank() over (order by priority, date_entered) as priority
...
I suspect since the rank can change so frequently, calculating it on the fly like this would be preferential to attempting to store the rank and keep it updated.
edit:
There is a logical flaw to this that I can spot already...if record 4 was inserted as priority 2 (so the database contains 2 priority 2 records), there really wouldn't be an easy way to inject ID 5 between ID 4 and 2 without manipulating the date_entered field.
second edit:
Allowing the priority column to be decimal (priority 2 entered, then priority 2.5 entered, and so on), then using the rank() function to resolve that to an integer would get around that. There isn't a pretty answer here that I can find

SQL : Check if result = number for each id

I have this sort of structure
ID STATUS
1 FIRSTSTAT
2 FIRSTSTAT
3 FIRSTSTAT
1 SECSTAT
3 SECSTAT
3 THIRDSTAT
3 FOURTHSTAT
3 FIFTHSTAT
I want to get the 3 back because he has all following status (FIRSTSTAT, SECSTAT, THIRDSTAT). Do you have an idea how I could make that?
It should be done by explicitely giving the statuses because other statuses exist so SELECT FROM WHERE = 'THIRDSTAT' is not ok since it should have all three statuses, not only one of them.
So I guess it should be done calculating the SUM or something like that.
I tried the following but of course, it does not work :
SELECT
FROM
WHERE
AND
AND
If the number of different status values is known to always be 3:
select id
from tablename
where status in ('FIRSTSTAT', 'SECSTAT', 'THIRDSTAT')
group by id
having count(distinct status) = 3

subtract every next column value from previous?

I have a dataset, where somehow the next singular data is added on top of the previous data for one row, and that for every column, which means,
row with ID 1 is the original pure data, but row with e.g ID 10 has added the data from the previous 9 datasets on itself...
what I now want is to get the original pure data for every distinct item, which means for every ID, how can I substract all data from lets say ID, 10? I would have to substract those of the previous one, for ID 9 and so on...
I want to do this either in SQL Server or in Rapidminer, I am working with those tools, any idea?
here is a sample:
ID col1 col2 col3
1 12 2 3
2 15 5 5
3 20 8 8
so the real correct data for Item with ID 3 is not 20, 8, 8 it is (20-15),(8-5),(8-5) so its 5,3,3...
subtract the later from its previous for every item except the first..
1 12 2 3
Try it out with lag series operator, it will work for sure! To get this operator you should install the series extension from the RM marketplace.
What this operator does - he copies the selected attributes and pushes every row of the example set for one point, so row with ID 1 gets a copy with ID 2 etc (you can also specify the value for a lag). Afterwards you can substract one value from another with Generate Attributes.
I think lag() is the answer to your question:
select (case when id = 1 then col
else col - lag(col) over (order by id)
end)
However, sample data would clarify the question.
Within RapidMiner there is the Differentiate operator contained in the Series extension (which is not installed by default and needs to be downloaded from the RapidMiner Marketplace). This can be used to calculate differences between attributes in adjacent examples.

INFORMATICA Using transformation to get desired target from a single flat file (see pictures)

I just started out using Informatica and currently I am figuring out how to get this to a target output (flat file to Microsoft SSIS):
ID Letter Parent_ID
---- ------ ---------
1 A NULL
2 B 1
3 C 1
4 D 2
5 E 2
6 F 3
7 G 3
8 H 4
9 I 4
From (assuming that this is a comma-delimited flat file):
c1,c2,c3,c4
A,B,D,H
A,B,D,I
A,B,E
A,C,F
A,C,G
EDIT: Where c1 c2 c3 and c4 being a header.
EDIT: A more descriptive representation of what I want to acheive:
EDIT: Here is what I have so far (Normalizer for achieving the letter column and Sequence Generator for ID)
Thanks in advance.
I'd go with a two-phased approach. Here's the general idea (not a full, step-by-step solution).
Perform pivot to get all values in separate rows (eg. from "A,B,D,H" do a substring and union the data to get four rows)
Perform sort with distinct and insert into target to get IDs assigned. End of mapping one.
In mapping two add a Sequence to add row numbers
Do the pivot again
Use expression variable to refer previous row and previous RowID (How do I get previous row?)
If current RowID doesn't match previous RowID, this is a top node and has no parent.
If previous row exists and the RowID is matching, previous row is a parent. Perform a lookup to get it's ID from DB and use as Parent_ID. Send update to DB.