Lets say I have a DB built like this:
NUM VALUE
1 3.51
2 hello
1 3.487
2 goodbye
1 32.4
2 foo
what I need to do to add another column in which all the values having num "2" will be in.
e.g.
NUM VALUE value2
1 3.51 hello
1 3.487 goodbye
1 32.4 foo
any idea how I can do this?
thanks!
In this example I am using SQLite, where the table Source already has a built-in rowid. Depending on the database you are using, you may need to add your own auto-incrementing integer column (i.e., integer primary key), but the idea is the same.
CREATE TABLE Source (num, value);
INSERT INTO Source (num, value) VALUES (1, 3.51);
INSERT INTO Source (num, value) VALUES (2, 'hello');
INSERT INTO Source (num, value) VALUES (1, 3.487);
INSERT INTO Source (num, value) VALUES (2, 'goodbye');
INSERT INTO Source (num, value) VALUES (1, 32.4);
INSERT INTO Source (num, value) VALUES (2, 'foo');
"1","3.51"
"2","hello"
"1","3.487"
"2","goodbye"
"1","32.4"
"2","foo"
SELECT a.num, a.value, b.value
FROM Source a
INNER JOIN Source b ON a.rowid = b.rowid - 1
WHERE a.num = 1 AND b.num = 2
"1","3.51","hello"
"1","3.487","goodbye"
"1","32.4","foo"
Related
I want to update a column of JSONB objects. So If I have this table
I want to delete value1 and value2 from the rows that have a as 1 then I thought this query would work
UPDATE
test AS d
SET
b = b - s.b_value
FROM
(VALUES
(1, 'value1'),
(1, 'value2')
)
AS s(a, b_value)
WHERE
d.a = s.a
but it gives me this result where value1 was not eliminated.
Is there a simple way to fix it? I want to make a query to delete this sort of stuff but it would be a blessing if it can be done in only one query. I got the original idea from here and here you can test the SQL query
You can subtract a text[] array of keys from a jsonb value like so:
with s (a, b_value) as (
values (1, 'value1'), (1, 'value2')
), dels as (
select a, array_agg(b_value) as b_values
from s
group by a
)
update test
set b = b - dels.b_values
from dels
where dels.a = test.a;
db<>fiddle here
I have a table representing product groups. Groups are defined by row number and their Type. Hence here we have 2 groups, the group is defined by the Type A, the Type B being components.
Row number
Type
0
A
1
B
2
B
3
A
4
B
5
B
With just this data, I need to find back the row number of the last preceeding Type A occurence :
Row number
Type
Row father
0
A
0
1
B
0
2
B
0
3
A
3
4
B
3
5
B
3
I can't find a way to get this. It's a sort of lag() or first_value() based on condition. Here I have 2 groups of 2 components, but I can have more groups with different sizes. The only thing that defines the group are the row number : every row number under Type A (so with Type B) is a child of the above Type A, until next type A.
Thank you for your help
You can achieve the desired result by using a join in conjunction with a group-by.
Test Data
CREATE TABLE TEST (ROW_NUMBER integer, TYPE varchar(1));
INSERT INTO test VALUES (0, 'A');
INSERT INTO test VALUES (1, 'B');
INSERT INTO test VALUES (2, 'B');
INSERT INTO test VALUES (3, 'A');
INSERT INTO test VALUES (4, 'B');
INSERT INTO test VALUES (5, 'B');
Query
SELECT T.*, MAX(A.ROW_NUMBER) AS ROW_FATHER
FROM TEST T
LEFT JOIN TEST A
ON A.TYPE = 'A' AND a.ROW_NUMBER <= T.ROW_NUMBER
GROUP BY T.ROW_NUMBER, T.TYPE
ORDER BY T.ROW_NUMBER
Result
I have a number of tables that follow this rather common pattern: A <-->> B. I would like to find the pairs of matching rows in table A where certain columns have equal values and also have referencing rows in B where certain columns have equal values. In other words, a pair of rows (R, S) in A matches, iff for given sets of columns {a1, a2, …, an} in A and {b1, b2, …, bn} in B:
We have R.a1 = S.a1, R.a2 = S.a2, …, R.an = S.an.
For every R's referencing row T in B exists S's referencing row U in B s.t. T.b1 = U.b1, T.b2 = U.b2, …, T.bn = U.bn.
(R, S) matches iff (S, R) matches.
(I'm not very familiar with relational algebra, so my definition above might not follow any convention.)
The approach that I came up with was:
Find pairs (R, S) that have matching columns.
See if there's and equal number of (any) R's and S's referencing rows in B.
For each row in B find a matching row, group by the referencing row in A and count. Check that there are as many matching rows as referencing rows.
However, the query that I wrote (below) for steps 2 and 3, to find matching rows in B, is quite complex. Is there a better solution?
-- Tables similar to those that I have.
CREATE TABLE a (
id INTEGER PRIMARY KEY,
data TEXT
);
CREATE TABLE b (
id INTEGER PRIMARY KEY,
a_id INTEGER REFERENCES a (id),
data TEXT
);
SELECT DISTINCT dup.lhs_parent_id, dup.rhs_parent_id
FROM (
SELECT DISTINCT
MIN(lhs.a_id, rhs.a_id) AS lhs_parent_id, -- Normalize.
MAX(lhs.a_id, rhs.a_id) AS rhs_parent_id,
COUNT(*) AS count
FROM b lhs
INNER JOIN b rhs USING (data)
WHERE NOT (lhs.id = rhs.id OR lhs.a_id = rhs.a_id) -- Remove self-matching rows and duplicate values with the same parent.
GROUP BY lhs.a_id, rhs.a_id
) dup
INNER JOIN ( -- Check that lhs has the same number of rows.
SELECT
a_id AS parent_id,
COUNT(*) AS count
FROM b
GROUP BY a_id
) lhs_ct ON (
dup.lhs_parent_id = lhs_ct.parent_id AND
dup.count = lhs_ct.count
)
INNER JOIN ( -- Check that rhs has the same number of rows.
SELECT
a_id AS parent_id,
COUNT(*) AS count
FROM b
GROUP BY a_id
) rhs_ct ON (
dup.rhs_parent_id = rhs_ct.parent_id AND
dup.count = rhs_ct.count
);
-- Test data.
-- Expected query result is three rows with values (1, 2), (1, 3) and (2, 3) for a_id,
-- since the first three rows (with values 'row 1', 'row 2' and 'row 3')
-- have referencing rows, each of which has a matching pair. The fourth row
-- ('row 3') only has one referencing row with the value 'foo', so it doesn't have a
-- pair for the referenced rows with the value 'bar'.
INSERT INTO a (id, data) VALUES
(1, 'row 1'),
(2, 'row 2'),
(3, 'row 3'),
(4, 'row 4');
INSERT INTO b (id, a_id, data) VALUES
(1, 1, 'foo'),
(2, 1, 'bar'),
(3, 2, 'foo'),
(4, 2, 'bar'),
(5, 3, 'foo'),
(6, 3, 'bar'),
(7, 4, 'foo');
I'm using SQLite.
To find matching and different rows it is easier to use INTERSECT and MINUS operations then joins...
But when only one field actually used in comparison JOIN solution looks better:
Select B1.A_Id, B2.A_Id
From (
Select Data, A_Id, Count(Id) A_Count
From B
Group By Data, A_Id
) b1
inner join (
Select Data, A_Id, Count(Id) a_count
From B Group By Data, A_Id
) b2 on b1.data = b2.data and b1.a_count = b2.a_count and b1.a_id <> b2.a_id
As I understand you need to find out the pairs of different a_id which have same data and count of data.
The result of my script gives, the possible couples in two directions, that left room for optimization on SQLlite specific syntax.
Result example:
{1,2}, {1,3}, {2,1}, {2,3}, {3,2}, {3,1}
I have two tables in the database MyTable and MyTableChanges. I want to detect changes (which records were inserted/removed from MyTableChanges or edited).
Is it possible? I would like to do this using only SQLite queries.
I know I can use 2 queries like the one below to detect inserted and removed rows:
SELECT DISTINCT SomePrimaryKey
FROM MyTable
WHERE SomePrimaryKey Not IN
(SELECT DISTINCT SomePrimaryKey FROM MyTableChanges)
But how to compare changes? Maybe there's some way, dealing with hashes on columns and joins. I don't know how to start. Please, advise me!
EDIT
I know I can do something like this:
CREATE TABLE Test1
(
MI_PRINX INTEGER PRIMARY KEY AUTOINCREMENT,
Name CHAR(100),
Value INTEGER
);
CREATE TABLE Test2
(
MI_PRINX INTEGER PRIMARY KEY AUTOINCREMENT,
Name CHAR(100),
Value INTEGER
);
INSERT INTO Test1 (Name, Value) VALUES('Name1', 1);
INSERT INTO Test1 (Name, Value) VALUES('Name2', 2);
INSERT INTO Test1 (Name, Value) VALUES('Name3', 3);
INSERT INTO Test1 (Name, Value) VALUES('Name4', 4);
INSERT INTO Test2 (Name, Value) VALUES('Name1', 2);
INSERT INTO Test2 (Name, Value) VALUES('Name3', 3);
INSERT INTO Test2 (Name, Value) VALUES('Name4', 5);
INSERT INTO Test2 (Name, Value) VALUES('Name5', 6);
INSERT INTO Test2 (Name, Value) VALUES('Name6', 7);
INSERT INTO Test2 (Name, Value) VALUES('Name7', 8);
-- suppose Name is unique
SELECT * FROM Test1 JOIN Test2 ON Test1.Name = Test2.Name
WHERE Test1.Value <> Test2.Value
But it's kinda uncomfortable solution, because I need to create really long queries for many columns... Any other idea?
When you use a natural join, the database will join using all columns that have the same name.
In this case, this will allow you to compare entire records.
Then, using an outer join, you can find out which records do not have a matching record in the other table:
SELECT Table1.ID
FROM Table1 NATURAL LEFT JOIN Table2
WHERE Table2.ID IS NULL
I have the following table on SQL Server:
ID Num
1 A
2 B
2 B
3 C
3 C
4 C
(Num is a numeric column - A, B, and C are standins for numeric values, for the purpose of this question)
How to get the value of A+B+C+C without using subqueries and CTE?
A - for 1, B - for 2, C - for 3, C - for 4.
The answer seems to sum(distinct Num), but distinct is by ID field!
Demo table:
create table test (ID int, Num int);
insert into test values (1, 10);
insert into test values (2, 100);
insert into test values (2, 100);
insert into test values (3, 1000);
insert into test values (3, 1000);
insert into test values (4, 1000);
The correct answer is 10+100+1000+1000 = 2110.
A random guess, using CTE to avoid the pointless subquery restriction:
With X as (Select Distinct Id, No From Test)
Select
Sum(No)
From X
Or using a derived table (which works in SQL 2000):
Select
Sum(No)
From (
Select Distinct
Id,
No
From
Test
) a;
http://sqlfiddle.com/#!3/77a6e/6
The solution:
select cast(sum(distinct Num + cast(0.00001 as number(38,19))/ID) as number(18,2))