Remove semi-duplicate rows from a result set - sql

I have a logging table (TABLE_B) that is updated via triggers from a main table (TABLE_A). The trigger operates whenever any field on TABLE_A is inserted/updated. We need to pull a report out that shows only a subset of updates on TABLE_B - ie the user is only interested in the fields:
ID
STAGE
STATUS
UPDATE_DATE
I need to remove sequential duplicates from the result set, ie, suppose the following entries exist in TABLE_B:
+----+-----+------+-----------+
|ID |STAGE|STATUS|UPDATE_DATE|
+----+-----+------+-----------+
|4567|7 |9 |2012-12-25 |
+----+-----+------+-----------+
|4567|4 |2 |2012-12-24 |
+----+-----+------+-----------+
|4567|4 |3 |2012-12-23 |
+----+-----+------+-----------+
|4567|4 |2 |2012-12-22 |
+----+-----+------+-----------+
|4567|4 |2 |2012-12-21 |
+----+-----+------+-----------+
|4567|4 |3 |2012-12-20 |
+----+-----+------+-----------+
|4567|4 |2 |2012-12-19 |
+----+-----+------+-----------+
From the bottom, I need to extract rows 1,2,3,5,6,7 - omitting row 4 only: I have 2 entries at rows 3 & 4 that are duplicates (row 4 has been triggered into TABLE_B because of an update to some other field in TABLE_A, but it's stage/status combination hasn't altered therefore it can be ignored).
So, when I discover that the next row in a result set is a duplicate (and only the next row) of the current row, how can I either remove it from the result set, or neglect to select it in the first place. I'll be performing the operation using a stored proc - will a cursor be involved in this?
Sybase 12.5, though the syntax is very close to SQL Server.

Had a look at a similar question on StackOF:
http://stackoverflow.com/questions/19774273/remove-duplicates-in-sql-result-set-of-one-table
I think this answers the question:
select id, status, stage, min(updated_date)
from TABLE_B
where id = <someValue>
group by id, status, stage

Related

If condition TRUE in a row (that is grouped)

Table:
|Months |ID|Commission|
|2020-01|1 |2312 |
|2020-02|2 |24412 |
|2020-02|1 |123 |
|... |..|... |
What I need:
COUNT(Months),
ID,
SUM(Commission),
Country
GROUP BY ID...
How it should look:
|Months |ID|Commission|
|4 |1 |5356 |
|6 |2 |5436 |
|... |..|... |
So I want to know how many months each ID received his commission, however (and that's the part where I ask for your help) if the ID is still receiving commission up to this month (current month) - I want to exclude him from the list. If he stopped receiving comm last month or last year, I want to see him in the table.
In other words, I want a table with old clients (who doesn't receive commission anymore)
Use aggregation. Assuming there is one row per month:
select id, count(*)
from t
group by id
having max(months) < date_format(now(), '%Y-%m');
Note this uses MySQL syntax, which was one of the original tags.

Fetch data from multiple tables in postgresql

I am working on an application where I want to fetch the records from multiple tables which are connected through foreign key. The query I am using is
select ue.institute, ue.marks, uf.relation, uf.name
from user_education ue, user_family uf where ue.user_id=12 and uf.user_id=12
The result of the query is
You can see the data is repeating in it. I only want a record one time. I want no repetition. I want something like this
T1 T2
id|name|fid id|descrip| fid
1 |A |1 1|DA | 1
2 |B |1 2|DB | 1
2 |B |1
Result which I want:
Result:
id|name|fid|id|descrip| fid
1 |A |1 |1|DA | 1
2 |B |1 |2|DB | 1
2 |B |1 |
The results fetched through your query
The total rows are 5
More Information
I want the rows of same user_id from both tables but you can see in T1 there are 3 rows and in T2 there are 2 rows. I do not want repetitions but also I want to fetch all the data on the basis of user_id
Table Schemas,s
T1
T2
I can't see why you would want that, but the solution could be to use the window function row_number():
SELECT ue.institute, ue.marks, uf.relation, uf.name
FROM (SELECT institute, marks, row_number() OVER ()
FROM user_education
WHERE user_id=12) ue
FULL OUTER JOIN
(SELECT relation, name, row_number() OVER ()
FROM user_family
WHERE user_id=12) uf
USING (row_number);
The result would be pretty meaningless though, as there is no ordering defined in the individual result sets.

How to read previous values in sql

I have a table where the IDs , Reference IDs and amounts are stored. The problem is that for the rows where reference IDs is set the amount is missing. I need to read the rows where reference_id = ID and read the amount and set the value (like it is shown in Table2).
+--+------------+------+
|ID|Reference ID|Amount|
+--+------------+------+
|1 | |300 |
+--+------------+------+
|2 |1 | |
+--+------------+------+
I want to be able to show:
Table 2
+--+------------+------+
|ID|Reference ID|Amount|
+--+------------+------+
|1 | |300 |
+--+------------+------+
|2 |1 |300 |
+--+------------+------+
Anyone has any idea whats the best way to find this missing value?
Best Regards.
MEJ
I think you want a self-join:
select t1.id, t1.referenceid, coalesce(t2.amount, t1.amount) as amount
from table1 t1 left outer join
table1 t2
on t1.id = t2.referenceid;
I think you want a hierarchical query:
select id, ref_id, connect_by_root amount
from <your table>
connect by prior id = ref_id
start with ref_id is null;
SQL Fiddle.
More about the connect_by_root operator in the documentation.
This allows for multiple levels since it always goes back to the root for the amount. But that kind of assumes that the child records never have an amount themselves, or it can be ignored. You can use nvl to the the child value if it is set, but children of that will still go back to the root. You can add an amount null check to the conditions if you want to show the previous value:
select id, ref_id, connect_by_root amount as amount
from <your table>
connect by prior id = ref_id and amount is null
start with ref_id is null or amount is not null
order by id;
SQL Fiddle.

Fetching row of a table and moving across column of another table

Given a table like this with single column,
Names
------
A
B
C
D
E
Take each record from table and check previous and next value and put it across new table.
Print 'null' if no previous or next value exists with column name as prev_name,current_name,next
Prev_name| Current name| next
-----------------------------
NULL | A |B
A | B |C
B | C |D
C | D |E
D | E |NULL
I am learning SQL and googled to find something which might help solve this but couldn't.
Any help will be great!
See this link in fiddle, Query. But NULLS are considered as spaces and omitted in string concatenation.
Please use this query
SELECT LAG(NAMES) OVER(ORDER BY NAMES) AS PREV_NM, NAMES,
LEAD(NAMES) OVER(ORDER BY NAMES) AS NEXT_NM
FROM SAMPLE
Fiddle link is changed.

sum rows from one table and move it to another table

How can I sum rows from one table (based on selected critiria) and move the outcome to another table.
I have a table related to costs within project:
Table "costs":
id| CostName |ID_CostCategory| PlanValue|DoneValue
-------------------------------------------------------
1 | books |1 |100 |120
2 | flowers |1 |90 |90
3 | car |2 |150 |130
4 | gas |2 |50 |45
and I want to put the sum of "DoneValue" of each ID_CostCategory into table "CostCategories"
Table "CostCategories":
id|name |planned|done
------------------------
1 |other|190 |takes the sum from above table
2 |car |200 |takes the sum from above table
Many thanks
I would not store this, because as soon as anything changes in Costs then CostCategories will be out of date, instead I would create a view e.g:
CREATE VIEW CostCategoriesSum
AS
SELECT CostCategories.ID,
CostCategories.Name,
SUM(COALESCE(Costs.PlanValue, 0)) AS Planned,
SUM(COALESCE(Costs.DoneValue, 0)) AS Done
FROM CostCategories
LEFT JOIN Costs
ON Costs.ID_CostCategory = CostCategories.ID
GROUP BY CostCategories.ID, CostCategories.Name;
Now instead of referring to the table, you can refer to the view and the Planned and Done totals will always be up to date.
INSERT INTO CostCategories(id,name,planned,done)
SELECT ID_CostCategory, CostName, SUM(PlanValue), SUM(DoneValue)
FROM costs GROUP BY ID_CostCategory, CostName