Between variables sql - sql

I've been thinking about this but didn't get a solution yet.
I have 2 tables
TABLE1
FrID FrCode Zstart ZEnd
-------------------------
1 AQ 10000 20000
2 AW 34578 67459
3 SR 86428 89758
TABLE2
ID NAME ZIP
-------------
1 XXX 35864
2 CCC 25758
3 FFF 87526
I need to get the frCode if the ZIP is between Zstart and ZEnd.
The problem is that I don't have a primary key to joint the tables.
I know a between clause can help but not sure how to do for all values.
Note: Id and FrID are not key values

Between is a common SQL construct to use for querying between date ranges so to get frCode between start and end you can do something like below
SELECT t1.FrCode
FROM TABLE1 t1
JOIN TABLE2 t2 ON t1.FrID = t2.ID
WHERE t2.ZIP BETWEEN t1.Zstart AND t1.ZEnd
If the FrID and ID are not related, then there must be some relation between Table1 and Table2 right if you want to get FrCode then you will need to join on that relation
ON t1.FrID = t2.OtherColumn

Related

Delete a record from a table referring to 2 or more columns from another table

Consider having 2 tables as follows.
Table 1:
Unit
SKU number
Active
A
1
Y
B
2
Y
c
3
Y
Table 2:
Unit
SKU number
description
X
4
Apple
B
2
Mango
Y
5
Grapes
z
6
Banana
I wanted to delete record B,2,Y from table 1 by referring to table 2 where values in columns Unit and SKU number match.
I tried using the following query but it didn't seem to work
DELETE FROM table1
WHERE (Unit, SKU_Number) IN (SELECT Unit, SKU_Number FROM table2);
The error was
An expression of non-boolean type specified in a context where a condition is expected, near ','
Can someone please help me understand what I am doing wrong here or help me rewrite the SQL query to achieve the required objective?
You could use similar logic with exists:
DELETE
FROM table1 t1
WHERE EXISTS (SELECT 1 FROM table2 t2
WHERE t2.Unit = t1.Unit AND t2.SKU_Number = t1.SKU_Number);
You can try using this query, assuming Unit of Table 1 is unique:
DELETE FROM table1
WHERE table1.Unit IN (
SELECT table1.Unit
FROM table1
LEFT JOIN table2 ON table1.Unit = table2.Unit
AND table1.SKU_Number = table2.SKU_Number
)
If unit is not an unique field, simply replace it with whichever field is unique, or with primary key of Table 1.
You can use inner join for delete:
DELETE t1
FROM table1 t1
INNER JOIN table2 t2
ON t1.unit=t2.unit and t1.SKU_Number = t2.SKU.Number

How to use Like operator to match a string in one table to a sub-string into another table

I have to two tables Table 1 & Table 2. Table 1 has customer details and Table 2 has transaction details:
Table 1 Table 2
Col1 CustCode Col1 TrainsactionID Col3
11 AAA 101 2139812/BBB/98waw EDF
22 BBB 102 2398472/CCC/18sdf QWD
33 CCC 103 9283743/AAA/76afa VFB
44 DDD 104 2983472/BBB/123as FGV
I need to select the customer codes (strings) AAA, BBB and CCC from column "CustCode" of table 1 as they exist as a substring in column "TransactionID" of table 2.
Is there a way I can write a correlated subquery using 'Like %' operator to fetch all such matching CustCodes?
You may use a join, on the condition that the customer code from the first table appears in the path of the transaction ID from the second table.
SELECT t1.Col1, t1.CustCode, t2.Col1, t2.TrainsactionID, t2.Col3
FROM Table1 t1
INNER JOIN Table2 t2
ON t2.TrainsactionID LIKE '%/' + t1.CustCode + '/%';
Demo
Note that this join condition is not optimal and probably can't use an index. If you have a long term need for these tables, then consider setting up join columns which can use equality operators.
You can try below -
select A.col1, a.custcode,b.transactionid,b.col3
from table1 a inner join table2 b
on a.CustCode like concat('%',b.TrainsactionID,'%')

SQL comparing two sets of complex data

Sorry, probably the title is not the best one but I hope you will understand what problem I have.
I need to compare and analyse two sets of data and I'm using MS-Access for that. My data is organized in two tables. Following is not the real data I'm working with but will serve ok as example:
TABLE 1
ID Name
1 Zoie
2 Rohan
2 Simon
3 Jerome
4 Jakob
4 Mathew
4 Cora
6 Keely
7 Aiyana
7 Jake
8 Reid
9 Emerson
TABLE 2
ID Name
1 Michael
2 Rohan
2 Simon
3 Jill
4 Jakob
4 Cora
5 Charlie
7 John
8 Reid
9 Yadiel
9 Emerson
9 Paris
So, I need to select only those IDs which fully corresponds (all names under specific IDs are the same) in both tables and those are: 2 and 8
I would also like to have separate select statement which will result with IDs 2 and 8 but also IDs with names from table 1 which also appears in table 2 (all from table 1 plus possible some extra in table 2 under the same ID). So that would be: 2, 8, 9
I would also like to have separate select statement which will result with IDs 2 and 8 but also IDs with names from table 2 which also appears in table 1 (all from table 2 plus possible some extra in table 1 under the same ID). So that would be: 2, 4, 8
I would also like to have separate select statement which would be a combination of last two.
So result would be: 2, 4, 8, 9
I would appreciate any suggestions.
Thanks in advance!
Best regards,
Mario
Q#1:
select id
from table1
group by id
having count(*) =
(
select count(*)
from table2
group by table2.id
having table2.id = table1.id
)
and count(*) =
(
select count(*)
from table1 table1_1
inner join table2 on table1_1.id = table2.id and table1_1.name = table2.name
group by table1_1.id
having table1_1.id = table1.id
)
Explanation of this query:
It is grouping table1 by ID
For each group (for each ID), it is counting the number of rows in table1 that have this ID.
For each group, it is counting the number of rows in table2 that have this ID.
For each group, it is counting the number of rows where the name appears in both tables for this ID (it does that by inner joining table1 and table2 on the ID and Name which means only rows where both ID and Name match in both tables will be counted, for each ID).
It then returns IDs (from table1) where each of the above counts are equal. This is what results in returning IDs where all names are in both tables (no more, no less).
Q#2 - In this case you don't care that table2 has the same number of names per ID. So remove the first sub-query (that counts matching rows in table2).
select id
from table1
group by id
having count(*) =
(
select count(*)
from table1 table1_1
inner join table2 on table1_1.id = table2.id and table1_1.name = table2.name
group by table1_1.id
having table1_1.id = table1.id
)
Although the above is easy enough to understand following the same logic as Q#1, it is probably more efficient to do the following, and more straightforward. It only matters if you find it running too slow for your data (which is subjective and context dependent).
select table1.id
from table1
left join table2 on table1.id = table2.id and table1.name = table2.name
group by table1.id
having count(table1.id) = count(table2.id)
Here, the two tables are LEFT (outer) joined which means all records from table1 are gathered and records in table2 that match by ID and Name are also included alongside. Then, we group them by ID and we compare the count of each group in table1 with those that had matching names in table2.
Q#3 - This case is the same as Q#2 except table1 and table2 are swapped.
Q#4 - In this case you only care about IDs that have at least one name that appears in both tables. So join the tables and return the distinct IDs:
select distinct id
from table1
inner join table2 on table1.id = table2.id and table1.name = table2.name
Here is a SQLFiddle to play with containing the four queries: http://www.sqlfiddle.com/#!18/3fc71/22

SQL query using data from different tables

I need to create a query in SQL Developer.
There is Table1. Data in Table1 is as following:
Ex.1
ID_Number Time
12345 1
12345 2
12345 3
12345 4
12345 5
67890 1
67890 2
67890 3
etc.
This Table1 is connected to Table2 with this ID_Number and the Code_Number I need is in this Table2.
There is one BUT. For example in Table1 there are ID_numbers which has Time column as here in this example from 1-5. Then different ID_numbers and also from 1-5. Then there are some ID_numbers which has only for example 2, 4, 5 in Times column as below.
Ex.2
ID_Number Time
54321 2
54321 4
54321 5
I need to create a query that takes out all the Code_Numbers from Table2 (which is connected to Table1 via ID_number), but only those which doesn't have all those ID_numbers from 1-5 (Ex.1).
Is there any way to make this query possible? If I know that there is certain amount of them. For example 5, so maybe I could cound them with inner select and if there are lesst than 5 for example, then it will return these Code_Numbers for me?
This is what I gather from your comments and from guessing:
Code_Number in table2 is unique.
ID_Number in table2 is unique.
ID_Number in table1 is the ID of table2 and of course not unique in table1.
The combination ID_Number + Time in table 1 is unique.
So your data model could be more or less thus:
table2: code_number, code_name, ... Primary Key = code_number
table1: code_number, time, ... Primary Key = code_number + time
But you went for an ID concept, so you get:
table2: id_number, code_number, code_name, ... Primary Key = id_number, additional unique constraint on code_number
table1: id_number, time, ... Primary Key (or at least a unique constraint) = id_number + time
With better names for table and columns:
codes: id_code, code_number, code_name, ... PK = id_code, Unique Index on code_number
code_times : id_code_time, id_code, time_number, ... PK = id_code_time, Unique Index on id_code + time_number
Yes? Then you would select from codes table, but exclude records for which all requested time numbers exist in the code_times table. To find the id_number that have all time numbers, group by id_number and count the distinct time numbers. Then use the found IDs to access table2.
select code_number
from table2
where id_number not in
(
select id_number
from table1
where time in (1,2,3,4,5)
group by id_number
having count(*) = 5
);
If a code_number / time pair can occur more than once in table1, then replace count(*) with count(distinct time).
You need to use a join.
It would look something like:
SELECT t2.*
FROM t1
RIGHT OUTER JOIN t2 on t1.ID = t2.ID
WHERE t1.ID IS NULL
a RIGHT OUTER JOIN tells SQL to preserve the rows that don't match on the RIGHT hand table, by putting a NULL in the data from the left hand table.
We then filter where the left table is NULL, so we get the results that don't exist in the left table.
Updated SQL based on the comment:
SELECT t2.*
FROM t1
RIGHT OUTER JOIN t2 on t1.ID = t2.ID
AND t1.Time = t2.Time
WHERE t1.ID IS NULL
Also, note that the SQL syntax might change depending on what version you're using.
You can do this comparing counts from both the tables.
Fiddle
select t2.id
from t2
group by t2.id
having count(*) < (select count(*) from t1 where t1.id = t2.id group by t1.id)

How to create query who will be sum or not values from tables

I have table like this
Table1
ID Name Value fk_table
1 edd 3 1
2 tom 1 2
3 emi 2 NULL
And second table
Table2
ID VALUE
1 3
2 3
How to create query who will be sum value from table1 and table2 if is a foreign key, or will output only value from table1 if isn't fk
return $this->getEntityManager()
->createQuery('SELECT t1.name, SUM(t1.value as value +t2.value)
FROM AcmeBlogBundle:Table1 t1
LEFT JOIN t1.table2 t2')
->execute();
I want result like this
edd 6
tom 5
emi 2
I use doctrine and Symfony2
1 - You haven't specified the conditions you are joining on
2 - SUM function does not work like that - it sums aggregate on whole column, you just need a +
3 - Using COALESCE to ensure the missing values are replaced with 0
SELECT T1.Name, COALESCE(T1.VALUE,0) + COALESCE(T2.VALUE,0)
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.fk_table = T2.ID
SQLFiddleDemo (SQL Server in example, but should also work fine with other SQL flavors)
Your problem is that NULL 'zaps the life out of everything'. Adding it to any other value results in NULL. You should use COALESCE(t2.value, 0) to ensure it results a valid integer that doesn't interfere with the sum.