DB queries with "In" seem to be sorted - sql

There are clients(companies) and contacts in two tables. Both contacts and clients have their own fields. But they all have an id that is a primaryKey. In addition, there are "links" between clients and contacts - each client can be assigned a contact and vice versa. There is a third table for this, called 'assignment', which has only two fields - company id and contact id.
Suppose we have linked a contact with id 3 to a company with id 12076. Next, we have linked a contact with id 10, and the last contact with id 5. Сheck our result:
SELECT contactId FROM assignment WHERE companyId = 12076;
The result is correct -
After these steps, at some point I need to get the FIELDS of contacts associated with the company I need. There is a company 12076, I need to get all the contact fields associated with it. I made a request like this:
SELECT id, fullName FROM contacts WHERE contacts.rowid IN (SELECT contactId FROM assignment WHERE companyId = 12076);
This request displays the contacts I need and their fields. Exactly 3 contacts, but there is one problem - they are displayed in sorted order, sorted by id.
I need the contact fields to be displayed in the order in which they were added. How can i dow this? Maybe i need to use JOIN?

By default an SQLite table has a Rowid column. We can use this column in ORDER BY.
If we want the ContactId's in the order they were inserted into the table contacts we can join onto contacts and order by it's Rowid.
See [https://www.sqlitetutorial.net/sqlite-autoincrement/][1]
create table companies(id int);
create table contacts (id int);
create table assignment(companyId int,contactId int);
insert into companies values(12076);
insert into contacts values(10),(3),(5);
insert into assignment values (12076,3),(12076,10),(12076,5);
SELECT a.contactId
FROM assignment a
JOIN contacts c
on a.contactId = c.id
WHERE companyId = 12076
order by c.Rowid;
| contactId |
| --------: |
| 10 |
| 3 |
| 5 |
db<>fiddle here

Related

SQL Query to fetch the customers registered in the DB without email address(CS can have phonenumber and email in the same field but duplicating)

I need help with writing this query please ,
in the Database - the customer is registered twice , one row with the email address in the VALUE field and the other row with phone number in the SAME VALUE field .
I want to fetch customer who DO NOT HAVE email address in the VALUE FIELD .
For example , I want to fetch only the last row from the list shown in the figure I shared.
Appreciate your help!
I tried creating multiple SELECT queries , but still not getting the accurate values.
Without seeing table schemas or example data, I'm making an assumption here that you have a field that is common to both rows so you know the customer row with the email value and the customer row with the phone value are linked to the same customer. For the purposes of this example, I'm going to call that field "customer_number".
I'd suggest a query that utilises an auxiliary statement like this:
WITH customers_with_emails AS (
SELECT customer_number
FROM customers
WHERE customer_value LIKE '%#%'
)
SELECT *
FROM customers
WHERE customer_number NOT IN (
SELECT customer_number
FROM customers_with_emails
);
This will return customers with phone numbers, who do not also have an email address.
I suggest that you use the following query, modified with the exact column and table name. We use string_agg to coalesce all the value fields for the same customer id and only show them if none of them contain an # sign.
create table customers(
id int,
name varchar(25),
value varchar(25));
insert into customers values
(1,'Mr A','1234'),
(1,'Mr A','a#b.c'),
(2,'Mr B','6789');
select
id,
max(name) "name",
string_agg(value,', ')
from
customers
group by
id
having
string_agg(value,', ') NOT LIKE '%#%';
id | name | string_agg
-: | :--- | :---------
2 | Mr B | 6789
db<>fiddle here

Update user id by looking up two other tables

I have a table/sql issue I don't know how to solve.
I need to update/create a table of user ids with order ids.
Therefore I have to get a new user_id, by searching for the email in an old list.
With the email adress I need to look up the new user id.
So the logic is like:
order_id -> look at the old user_id -> look at the email -> look at the new user_id
I tried to create an example:
---------------------
TABLE: USERS_OLD (a list of user ids and an email adress)
id email
1 test1#email.com
2 test2#email.com
3 test3#email.com
4 test4#email.com
---------------------
---------------------
TABLE: USER_ORDERS_OLD (the connection of an order id with a user id)
user_id order_id
1 DLEFGM
2 OPDFGT
3 UZDFGP
4 POIDSX
---------------------
---------------------
TABLE: USERS_NEW (a new list of users id with the same emails from table USERS_OLD)
id email
5 test1#email.com
9 test2#email.com
10 test3#email.com
17 test4#email.com
---------------------
What I want to create:
---------------------
TABLE: USER_ORDERS_NEW
user_id order_id
5 DLEFGM
9 OPDFGT
10 UZDFGP
17 POIDSX
---------------------
I have no idea how to do that action. I don't even know what to search for.
What I managed to do is a LEFT JOIN sql statement to compare the user ids and create a list of matching user_ids.
But I have no idea how to look up over even more tables...
Hopefully someone can help me.
If it's easier I could also try to do it in spreadsheets.
Thanks in advance!
Assuming you just want to return the query then use;
SELECT u3.id, u2.order_id
FROM USERS_OLD u1
JOIN USER_ORDERS_OLD u2 ON u1.id = u2.user_id
JOIN USERS_NEW u3 ON u1.email = u3.email;
However, if you want to write the result into a new table, then you need to create the table first.
CREATE TABLE USER_ORDERS_NEW (user_id INTEGER, order_id VARCHAR(50));
INSERT INTO USER_ORDERS_NEW (user_id, order_id)
SELECT u3.id, u2.order_id
FROM USERS_OLD u1
JOIN USER_ORDERS_OLD u2 ON u1.id = u2.user_id
JOIN USERS_NEW u3 ON u1.email = u3.email;
See Demo
With your example you should be able to accomplish this with this query
INSERT INTO user_orders_new (user_id, order_id) SELECT usr_new.id, ord_old.order_id
FROM users_old usr_old JOIN users_new usr_new ON usr_new.email = usr_old.email
JOIN user_orders_old ord_old ON ord_old.user_id = usr_old.id;
You may want to opt for a LEFT JOIN on the old order table if you intend to migrate the ids regardless of whether they have had an order or not although I assume that's not the intention to populate the new order table with new users ids that haven't made an order.

How to use multi table join query efficiently in SQL?

I have Problem statement in Apache Phoenix in which I need to combine three tables for the result.
I have three views over Hbase table, Schema is as follow
Table group:-
pk | Title | ownerId | data
Table Members:-
pk | parentId | Email | data
Table userinfo:-
pk | Email | First Name | Last Name
Now, I want to fetch groups whose title matches with input string if not matched then want to fetch groups whose members have a name that matches with the input string.
I already tried query as follow:-
select * from Group where pk like 'Prefix_%'
and (TITLE like '%A%'
or (OWNER_ID in
(
select parentId from MEMBERS where EMAIL in
( select distinct(EMAIL) from USER_INFO
where pk like 'PREFIX%' and
( FIRST_NAME like '%A%' or LAST_NAME like '%A%')
)
)
) ) order by TITLE limit 5;
But, it's taking too much time also tried Left Join Query with similar but not give expected result.
Please Suggest how can I improve this?

Business logic for identify SQL column update

I have a SQL table called contacts which as n number of rows where n is more than 10Lakh (1 million) rows.
Below is the table structure with dummy data
+---------------+------------+---------+-----------+---------+------------------------+
| email | department | title | state | country | cleansing_verification |
+---------------+------------+---------+-----------+---------+------------------------+
| xyz#email.com | h.r. | sr. Exe | telangana | Ind | - |
+---------------+------------+---------+-----------+---------+------------------------+
So, I have 4 schedulers to cleanse the data which is present in the above table, ie
department cleanser
title cleanser
state cleanser
country cleanser
Each cleanser will update the data of the respective columns. I have added one more column call cleansing_verification to identify which column is updated but not able to use properly.
One email can be touched by any of the cleansers. Which means all 4 can update the value or any 3 or any 2 or only 1.
So, the problem is I'm facing is How to identify which email is touched and which is not so that for remaining I can send an email notification.
If something more need let me know I will add in the question.
Thanks in advance.
So normally we don't do this in the world of database design, but you could use bitfields. So your cleansing_verification is a BIT(4) type column, and each cleanser gets a bit they can set:
department = B'1000'
title = B'0100'
state = B'0010'
country = B'0001'
When running i.e. state, you would then:
UPDATE contacts
SET cleansing_verification = cleansing_verification | B'0010'
WHERE -- whatever conditions you want to apply
If you wanted to check which rows were updated by a given cleanser, you check if the bit is set, e.g. for state:
SELECT * FROM contacts WHERE cleansing_verification & B'0010' = B'0010'
Working example on dbfiddle
Actually proper way to do it would be to introduce a new table with a foreign key back to the contacts table and a column for a cleanser, like (quick'n'dirty example):
CREATE TABLE contacts_verification
(
contact_id int references contacts(id),
cleanser int
)
Then if you want to mark a record you just insert the contact id and some sort of cleanser identification (1, 2, 3, 4), or you can use a text field and meaningful names if you really want:
INSERT INTO contacts_verification (contact_id, cleanser) VALUES (21386, 1)
Then just use JOIN to get back the records marked by a cleanser:
SELECT c.*
FORM contacts c
JOIN contacts_verification dep_verify
ON dep_verify.contact_id = c.id
AND dep_verify.cleanser = 1

SQL Return Specific Value for Duplicate rows

Here is my issue
I am using bulk import to import a CSV file into a table (InputTable). This table needs to be separated into 3 different tables with distinct values.
Tables are Client, Child Company, Contacts
Client has a one to many relationship to child company as well as to contacts.
The client Table has has two fields (name,status)
it is easy enough to pull in a distinct name from dbo.InputTable using this query...
insert into Client
(
Name
)
select distinct Name
from InputTable
this query will insert data like this
Name
One Company
Two Company
Three Company
However when i try this code
insert into Client
(
Name
,Status
)
select distinct Name
from InputTable
group by Name
,Status
I get this result
Name | Status
One Company | Active
Two Company | Active
Two Company | Terminated
Three Company | Active
Here is the kicker, If client is showing active in one row no matter how many rows then i need to show active for that Name record on the Client Table
if they are showin all terminated then i would need to copy in the terminated status to the client table for that row.
any ideas on how to accomplish this?
Thank you in advance
insert into Client (Name, status)
select name,
min(status) as status
from InputTable
group by name