Insert multiple records with join - join

I need some help in figuring out how to insert more than one records in a table using a join (when the join returns more than one values). So here is the scenerio:
Table A:
A_ID bigserial, Role Varchar(25), Description varchar(25)
Table B:
B_ID bigserial, Role Varchar(25), Code varchar(25)
Table A and B are connected with column Role.
Example Entries in Table_A:
1, A, Standard
2, B , Test
3, C, Test
4, D, Standard
Example Entries in Table_B:
1, A, ABC
2, B, XYZ
3, C, XYZ
4, D, ABC
Basically what I need to do is check for Roles where description = Test, then insert entry for this Custom Role to Table_B with Code = ABC (If entry doesn't exist already)
The following query will give me all the Test description Roles which do not have any entry with Code = ABC in table B
Query1:
SELECT ROLE FROM TABLE_A A
INNER JOIN TABLE_B B
ON A.ROLE=B.ROLE
WHERE A.Description ='Test'
AND B.CODE<>'ABC';
I have the following insert query:
insert into Table_B (Role , Code)
select (SELECT ROLE FROM TABLE_A A
INNER JOIN TABLE_B B
ON A.ROLE=B.ROLE WHERE A.Description ='Test'AND B.CODE<>'ABC'), 'ABC';
The above insert query only works when Query1 returns one role, however I am not sure how to insert into table_A when Query1 returns more than 1 results.
Can someone pls help? Not looking to use Stored Procs for the same
Thanks.
Edited:
Example Entries in Table_A:
1, A, Standard
2, B , Test
3, C, Test
4, D, Standard
5, E, TEST
Example Entries in Table_B:
1, A, ABC
2, B, XYZ
3, B, ABC
4, C, DEF
5, C, XYZ
6, D, ABC
7, E, XYZ
8, E, LLL
Query1 will not work here:
SELECT ROLE FROM TABLE_A A
INNER JOIN TABLE_B B
ON A.ROLE=B.ROLE
WHERE A.Description ='Test'
AND B.CODE<>'ABC';
Using this query now:
SELECT distinct ROLE FROM TB where role not in (
SELECT B.ROLE FROM TA A
INNER JOIN TB B
ON A.ROLE=B.ROLE
WHERE A.Description =Test
AND B.CODE=ABC)
and role in (select role from TA where Description =Test);
How will the insert work now?

You can make another column as 'Code'.
Something like:
insert into Table_B (Role , Code)
SELECT ROLE, 'ABC' CODE FROM TABLE_A A
INNER JOIN TABLE_B B
ON A.ROLE=B.ROLE WHERE A.Description ='Test' AND B.CODE<>'ABC';
So number of columns will be match.

Related

Join Table B and get values of different columns depending on values in a specific column from Table A

I want to join two tables via ID. The first table has all the IDs and a column with the column names from the other table. I did this with a case statement and if worked but I have like 50 differnet column names and more to come so I don't want to use the case statement. What can I do instead? I'm using Snowflake, this is what I have:
Table A:
tableA
Table B:
tableB
create table statements:
CREATE OR REPLACE TABLE
TABLE_A
(id INTEGER,
column_name VARCHAR);
INSERT INTO
test.TABLE_A
(id,column_name)
VALUES
(1,'column_1'),
(1,'column_2'),
(2,'column_2');
---------------------
CREATE OR REPLACE TABLE
TABLE_B
(id INTEGER,
column_1 VARCHAR,
column_2 VARCHAR);
INSERT INTO
TABLE_B
(id,column_1,column_2)
VALUES
(1,'value_1_1','value_1_2'),
(2,'value_2_1','value_2_2');
This is what I did but as I said this is bad for maintainance:
SELECT
a.ID,
a.COLUMN_NAME,
CASE
WHEN a.column_name = 'column_1'
THEN b.column_1
WHEN a.column_name = 'column_2'
THEN b.column_2
ELSE ''
END AS result
FROM
TABLE_A a
JOIN
TABLE_B b
ON
a.id = b.id
This gives me the following result:
result
How can I get this result without using the case statement or having to type the strings into any condition?

Select rows with no match in join table with where condition

In a Rails app with Postgres I have a users, jobs and followers join table. I want to select jobs that are not followed by a specific user. But also jobs with no rows in the join table.
Tables:
users:
id: bigint (pk)
jobs:
id: bigint (pk)
followings:
id: bigint (pk)
job_id: bigint (fk)
user_id: bigint (fk)
Data:
sandbox_development=# SELECT id FROM jobs;
id
----
1
2
3
(3 rows)
sandbox_development=# SELECT id FROM users;
id
----
1
2
sandbox_development=#
SELECT id, user_id, job_id FROM followings;
id | user_id | job_id
----+---------+--------
1 | 1 | 1
2 | 2 | 2
(2 rows)
Expected result
# jobs
id
----
2
3
(2 rows)
Can I create a join query that is the equivalent of this?
sandbox_development=#
SELECT j.id FROM jobs j
WHERE NOT EXISTS(
SELECT 1 FROM followings f
WHERE f.user_id = 1 AND f.job_id = j.id
);
id
----
2
3
(2 rows)
Which does the job but is a PITA to create with ActiveRecord.
So far I have:
Job.joins(:followings).where(followings: { user_id: 1 })
SELECT "jobs".* FROM "jobs"
INNER JOIN "followings"
ON "followings"."job_id" = "jobs"."id"
WHERE "followings"."user_id" != 1
But since its an inner join it does not include jobs with no followers (job id 3). I have also tried various attempts at outer joins that either give all the rows or no rows.
In Rails 5, You can use #left_outer_joins with where not to achieve the result. Left joins doesn't return null rows. So, We need to add nil conditions to fetch the rows.
Rails 5 Query:
Job.left_outer_joins(:followings).where.not(followings: {user_id: 1}).or(Job.left_outer_joins(:followings).where(followings: {user_id: nil}))
Alternate Query:
Job.left_outer_joins(:followings).where("followings.user_id != 1 OR followings.user_id is NULL")
Postgres Query:
SELECT "jobs".* FROM "jobs" LEFT OUTER JOIN "followings" ON "followings"."job_id" = "jobs"."id" WHERE "followings"."user_id" != 1 OR followings.user_id is NULL;
I'm not sure I understand, but this has the output you want and use outer join:
SELECT j.*
FROM jobs j LEFT JOIN followings f ON f.job_id = j.id
LEFT JOIN users u ON u.id = f.user_id AND u.id = 1
WHERE u.id IS NULL;

ActiveRecord, Nested includes with counter

I have 3 tables (a, b, c) and "a" has_many "b" and "b" has_many "c". I have this line c.includes(b: :a), but I need to count how many "a" are for each "c" so the results be like 2 columns. Also there are some data in C that doesn't have b, so when I show them, it throw me an error.
I can do it with a query from pgAdmin and it show me how I need it but I can't make it on ActiveRecords.
The query that works fine is:
select count(c.id), a.name from c
left Join b on b.id = c.b_id
left join a on a.id = b.a_id
where c.created_at between '2018-11-08 00:00:00' and '2018-11-08 23:59:59' group by a.name
A.
joins(:b).
joins(b: :c).
group("a.name").
where("c.created_at between ? and ?", DateTime.new(2018,
11, 08), DateTime.new(2018, 11, 08).end_of_day).
count
returns a hash where the keys are "a.name" and the values are the count of C for each A.
If you only want to count unique C for each A, you can specify count("distinct c.id").
For more complex queries you can always query with raw SQL:
ActiveRecord::Base.connection.execute(<<~SQL).values
select count(c.id), a.name from c
left Join b on b.id = c.b_id
left join a on a.id = b.a_id
where c.created_at between '2018-11-08 00:00:00' and '2018-
11-08 23:59:59' group by a.name
SQL
returns a jagged array of the results.
As for your orphaned C records, when you query for them you can inner join to B. That will only return C that have B.

How to use group by in Informix?

I'm going to use the group by clause...max().
I'm using Informix version 10.
This is example table: table_a
col_a col_b col_c
1 20181010 3
1 20181030 4
I want to retrieve data with a recent date.
I want result :
col_a col_b col_c
1 20181030 4
When I use this query
#query 1: select col_a, max(col_b), col_c from table_a group by col_a
#result : The column (col_c) must be in the GROUP BY list.
#query 2: select col_a, max(col_b), col_c from table_a group by col_a, col_c
#result :
col_a col_b col_c
1 20181010 3
1 20181030 4
I think can I use MS SQL of row_num(partition by col_b)? but
Informix version 10 can't use row_num...
So, I use a join query
select a.col_a,a.col_b,a.col_c from table_a a
inner join (select col_a, max(col_b) as col_b from table_a group by col_a) b
on a.col_a = b.col_a and a.col_b = b.col_b
I got the results I wanted.
Is there a way to use join?

DQL Select Join

I'm trying to make a DQL query (doctrine from symfony 2.2) with no success on these entities:
Lesson
Which has several LessonContent
Which are each linked to a User
I want to retrieve all the lessons of a user (should be pretty basic...).
SELECT l, lc FROM MyBundle:LessonContent lc
JOIN lc.lesson l JOIN lc.modifiedBy u
WHERE lc.creation=1 AND u.id = :userId
But this returns the LessonContent entities. If I select from Lesson, I can't JOIN the lessons (which is probably what I should be doing).
Can anyone help me?
The main table you query from is what doctrine gives you back as the main objects, so the following should work (assuming l.content points to the LessonContent association):
SELECT l, lc FROM MyBundle:Lesson l
JOIN l.content lc
JOIN lc.modifiedBy u
WHERE lc.creation=1 AND u.id = :userId
It turned out I needed to have a l.content*s* attribute in order to be able to select from lessons and then JOIN on the rest.
Entity:
/**
* #var ArrayCollection $contentHistory
* #ORM\OneToMany(targetEntity="AAA\CoreBundle\Entity\LessonContent", mappedBy="lesson", cascade={"persist", "remove"})
* #ORM\OrderBy({"lastModified" = "DESC"})
*/
private $contentHistory;
Query:
SELECT l FROM AAACoreBundle:Lesson l JOIN l.contentHistory lc JOIN lc.modifiedBy u WHERE lc.creation=1 AND u.id = :userId GROUP BY l
And with that it works like a charm!

Resources