I have 3 tables on my SQLite db as follow:
TABLE first_names
id
name
gender
TABLE last_names
id
name
TABLE names
id
first
last
gender
birthday (null)
used (default 0)
Where first and last are unique and also have a index with both being unique on the names table.
In order to fed names table I have used the below query, which worked the first time but after I had added a new name to the last_names and tried to use it again it failed.
INSERT INTO names (first, last, gender)
SELECT f.name AS first, l.name AS last, f.gender AS gender
FROM first_names f
LEFT JOIN last_names l
WHERE f.name NOT IN (SELECT first FROM names) AND
l.name NOT IN (SELECT last FROM names)
Have also tried using (first, last, gender, [birthday], [used]) with values as null AS [birthday], 0 AS [used] but since it birthday is set to null on the table design and used to 0 as default and it worked on the first time didnt think it would be needed nor it made any difference anyway.
I would think it is because of the unique fields however I do have a WHERE to make sure the names are not already in the table names.
I have tried the query using C# and SQLiteAdmin both executing without requesting result or else it doesnt work.
What is wrong with my query and why it only works once ?
Try using:
WHERE NOT EXISTS ( SELECT * FROM names n WHERE n.first=f.name AND n.last=l.name)
You're not checking that the first and last names are on the same record
I haven't run this through a sql command line, but it should work:
INSERT INTO names (first, last, gender)
SELECT f.name AS first, l.name AS last, f.gender AS gender
FROM first_names f
LEFT JOIN last_names l
WHERE f.name NOT IN (SELECT subquery.first FROM (SELECT * FROM names WHERE l.name = last AND f.gender=gender) subquery)
Your query only works once because even if you have added another name to last_names, there is no value in first_names.name which is not present in names.first:
WHERE
f.name NOT IN (SELECT first FROM names) AND
l.name NOT IN (SELECT last FROM names)
All the posible values for f.name are included in SELECT first FROM names
Perhaps you want to join these clauses with an OR, rather than an AND.
Related
I am trying to count distinct values on Z_l based on value by using with clause. Sample data exercise included below.
please look at the picture, the distinct values of Z_l based on X='ny'
with distincz_l as (select ny.X, ny.z_l o.cnt From HOPL ny join (select X, count(*) as cnt from HOPL group by X) o on (ny.X = o.Z_l)) select * from HOPL;
You don't even need a WITH clause, since you just need one single sentence:
SELECT z_l, count(1)
FROM hopl
WHERE x='ny'
GROUP BY z_l
;
I need to write a code in sql that writes "del_row" in the column "Adjustment_name" when there are duplicated Id_numbers (e.g:234566) but just when one of the values in Phone_number start with A and other one start with B and in that case, it will write "del_row" just in the row in which the value in column "Phone_number" starts with "B". Imagine that I have two duplicated id_numbers and in one of them, the Phone_number starts with A and in the other row starts with "C". In this last situation, I don't want to write anything.
Id_number
Phone_number
Adjustment_name
234566
A5258528564
675467
A1147887422
675534
P1554515315
234566
B4141415882
del_row
234566
C5346656665
Many thanks!
One approach
SELECT t.id_number, t.Phone_number,
CASE WHEN a.id_number IS NOT NULL THEN 'del_row' ELSE '' END as Adjustment_name
FROM mytable t
LEFT JOIN
(SELECT id_number from mytable
WHERE SUBSTRING(Phone_number FROM 1 FOR 1)='A') a
/* List of IDs that have a phone number starting with A */
ON a.id_number = t.id_number
AND SUBSTRING(t.Phone_number FROM 1 FOR 1)='B'
/* Only check for matching ID with A if this number starts with B */
A rather crude approach would be as below
(assuming your phones rank Axxx, Bxxx, Cxxx, Dxxx). If your phone numbering logic is different - which is not very clear from your req - you can adjust accordingly.
create table temp_table_1 as (
select id_number, phone_number
, case
when dense_rank() over(partition by id_number order by phone_number)>1
and phone_number like 'B%'
then 'del_row'
end adjustment_name
from your_table_name
) with data;
drop table your_table_name;
rename table temp_table_1 to your_table_name;
SELECT Personeelsnummer, Achternaam, Voornaam, Departement, SubDep, SubSubDep, FTE, RedenUitDienst, Anciennitëitsdatum, GeldigOp, Schrapping, Ancienniteit, Positie, Nieveau, OmschrijfingStatuut
FROM tbl_Worker
GROUP BY Personeelsnummer
OR
SELECT (DISTINCT Personeelsnummer), Achternaam, Voornaam, Departement, SubDep, SubSubDep, FTE, RedenUitDienst, Anciennitëitsdatum, GeldigOp, Schrapping, Ancienniteit, Positie, Nieveau, OmschrijfingStatuut
FROM tbl_Worker
GROUP BY Personeelsnummer
I have a worker table with 49000 records, this includes a 'snapshot' from all workers EVERY month. But what I need is a table with all employees the company 'ever' had but only once. so I tried to wright the query's show above but they are not working.
So what I need is a query that shows all unique 'Personeelsnummers' with all the extra information about these persons.
what does work is this: SELECT DISTINCT Personeelsnummer FROM tbl_Worker ==> this gives me a table with 1200 records but only the numbers but I need all the extra information.
Instead of GROUP BY, use WHERE to get the first or last record:
SELECT w.*
FROM tbl_Worker as w
WHERE monthcol = (SELECT MAX(w2.monthcol)
FROM tbl_Worker as w2
WHERE w2.Personeelsnummer = w.Personeelsnummer
);
You would use MIN() to get the first month's record. My Dutch is a bit weak, so I don't know which column refers to the date for the record.
For performance, you want an index on tbl_Worker(Personeelsnummer, GeldigOp):
create index idx_tbl_worker_Personeelsnummer_GeldigOp on tbl_Worker(Personeelsnummer, GeldigOp);
EDIT:
Or you can do it with a JOIN:
SELECT w.*
FROM tbl_Worker as w INNER JOIN
(SELECT Personeelsnummer, MAX(GeldigOp) as max_GeldigOp
FROM tbl_Worker
GROUP BY Personeelsnummer
) as ww
ON ww.Personeelsnummer = w.Personeelsnummer and ww.max_GeldigOp = w.GeldigOp;
You're looking for a group by:
select *
from table
group by field1
Which can occasionally be written with a distinct on statement:
select distinct on field1 *
from table
As seen in this topic.
I am new to sql and trying to come up with a sql query which will list me the duplicate staff which were created in our system.
We have one staff which is created with id as 1234 and the same user has another account starting with staff id 01234. Is there anyway i can get the matching staff
Once i come up with correct duplicates i will than want to delete the accounts which don't have "0" at the start e.g deleted 1234 and only keep 01234
below is the sql
SELECT tps_user.tps_title AS [Name] , tps_user_type.tps_title AS [User Type]
FROM tps_user INNER JOIN
tps_user_type ON tps_user.tps_user_type_guid = tps_user_type.tps_guid
WHERE (tps_user.tps_title IN
(SELECT tps_title AS users
FROM tps_user AS t1
WHERE (tps_deleted = 0)
GROUP BY tps_title
HAVING (COUNT(tps_title) > 1))) AND (tps_user.tps_deleted = 0)
When you do you select try this:
SELECT DISTINCT CONVERT(INT,ID)
FROM your_table
WHERE ...
OR
SELECT ID
FROM your_table
WHERE ...
GROUP BY ID
This will convert all the id's to an int temporarily so when the distinct evaluates duplicates everything will be uniform to give you an accurate representation of the duplicates.
IF you don't want to convert them maybe convert them and insert them into a temporary table and add a flag to which ones have a leading zero. Or convert them then append a zero after you delete the duplicates since you want that anyway. It is easy to append a 0.
the below query will give you the list of duplicates with same Name and title. -
SELECT tps_user.tps_title AS [Name] ,
tps_user_type.tps_title AS [UserType],
COUNT(*) Duplicate_Count
FROM tps_user
INNER JOIN tps_user_type
ON tps_user.tps_user_type_guid = tps_user_type.tps_guid
group by tps_user.tps_title, tps_user_type.tps_title
having COUNT(*) > 1
order by Duplicate_Count desc
Select t1.stringId
from mytable t1
inner join mytable t2 on Convert(INT, t1.intId) = CONVERT(INT, t2.intId)
where t1.stringId not like '0%'
This should list all the persons that have duplicates but do not start with 0.
I have 2 tables, Student and Supervisor:
STUDENT(supervisorid(pk),name,email....)
SUPERVISOR(supervisorid(pk),name,email....)
Now I need to print supervisor name, email and the # of students under the supervisor (they will have same supervisor id). Something like:
select supervisorname,
supervisoremail,
tot_stud as (select count(*)
Phd_Student s
where s.supervisor_id = r.supervisor_id)
from Phd_Supervisor r
Can you please tell me the SQL query for this.
You will want to use the group by clause for this query. You can specify all of the fields that you want to display, as well as the count(*), join the tables, relate the tables , and then put in your group by clause, listing all of the display fields,(without the count(*)), as those are the fields you are grouping the students by to get their count.
select supervisorname,
supervisoremail,
(select count(*)
from Phd_Student s
where s.supervisor_id = r.supervisor_id) as tot_stud
from Phd_Supervisor r