How do I join on one column being a prefix of another? - mysql

Given two tables containing path columns that indicate the hierarchical placement in an organization, and emp1 that is a member of team1 in department1 in company acme (an emp can have multiple paths), and department managers (one manager can manage several departments):
create table emp (
username varchar(10),
path varchar(255)
);
create table manages (
username varchar(10),
path varchar(255)
);
insert into emp (username, path)
values ('emp1', '/acme/dept1/team1'),
('emp1', '/acme/dept9'),
('emp2', '/acme/dept2/team1');
insert into manages (username, path)
values ('mngr1', '/acme/dept1'),
('mngr2', '/acme/dept2'),
('mngr2', '/acme/dept3');
How can I check if emp1 is a subordinate of mngr1, i.e. if there is a manages.path that is a prefix of emp.path?
Something like:
select manages.username
from emp
join manages on manages.path is-prefix-of emp.path
where emp.username = 'emp1' and manages.username = 'mngr1'
which should return mngr1.
The actual path implementation is based on a fixed length primary key encoding (meaning that by construction /acme/dept1 wouldn't be a prefix of /acme/dept10).

Use a LIKE expression here:
SELECT m.username
FROM emp e
INNER JOIN manages m
ON e.path LIKE CONCAT(m.path, '%')
WHERE e.username = 'emp1' AND m.username = 'mngr1';
The LIKE expression in the above query says that e.path starts with m.path.

Related

MySQL select and match two tables and update column based on matched data

It seems difficult for me to thats why I need your help. So basically, I got two tables named xp_pn_resale and xp_guru_properties. What I need to do is update or set the column postal_code from table xp_pn_resale based from the data from another table. So here are my tables
My xp_pn_resale table, I wrote query like this in order to show you
SELECT postal_code,
block,
concat(block,' ', street_name) as address
FROM xp_pn_resale
where street_name like '%ANG MO KIO%';
And I get the result like this
As you can see, there are null values there and there are some postal_code that has values because I manually update them based on what I searched. I just want to automatically fill the postal_code from the query I got from other table.
Here is my xp_guru_properties table and I wrote query like this in order to show you
SELECT property_name as GURU_PROEPRTY_NAME,
property_type as GURU_PROPERTY_TYPE ,
JSON_UNQUOTE(JSON_EXTRACT(xp_guru_properties.json, '$.postcode') )as GURU_POSTCODE
FROM xp_guru_properties
where property_type like '%HDB%' AND property_name like '%ang mo kio%';
And the result is like this
xp_guru_properties got a column property_type which is a bit similar in the concatinated columns of block and street_name from other table I named it as GURU_PROPERTY_NAME.
As you can see, there is the virtual column named GURU_POSCODE. The values of that column is what I want to fill in the postal_code column from xp_pn_resale table. I was doing it manually to update the postal_code by doing
UPDATE xp_pn_resale
SET postal_code = 560110
WHERE street_name LIKE '%ANG MO KIO%'
AND block = 110
which is very tedious to me. Does anyone know how could I automatically update it based on the queries I showed ? Help will be appriciated.
EDIT: I wrote a JOIN query like this but this is for the record Lingkong Tiga which i manually filled all the postal_code
select distinct
JSON_UNQUOTE(json_extract(g.json, '$.postcode')) postcode,
JSON_UNQUOTE(json_extract(g.json, '$.name')) name,
JSON_UNQUOTE(json_extract(g.json, '$.streetnumber') )streetnumber,
p.block, p.street_name, p.postal_code
from xp_pn_resale p
inner join xp_guru_properties g
on g.property_name = concat(p.block, ' ', p.street_name)
where g.property_type like '%HDB%' AND g.property_name like '%Lengkong Tiga%'
I got result like this
Join the two tables and update.
UPDATE xp_pn_resale AS r
JOIN xp_guru_properties AS p ON concat(r.block,' ', r.street_name) = p.property_name
SET r.postal_code = JSON_UNQUOTE(JSON_EXTRACT(xp_guru_properties.json, '$.postcode') )
WHERE r.street_name like '%ANG MO KIO%'
AND p.property_type like '%HDB%' AND p.property_name like '%ang mo kio%'
AND r.postal_code IS NULL

Sequel to get select EVERY input

I have created three tables
CREATE TABLE guest(
name varchar(100),
ranking int,
PRIMARY KEY (name)
);
CREATE TABLE room(
roomname varchar(100),
wallcolor varchar(100),
rating int,
PRIMARY KEY(roomnane)
);
CREATE TABLE reservation(
name varchar(100),
roomname varchar(100),
day varchar(100),
moveinday int,
moveoutday int,
PRIMARY KEY(roomname, day, start, finish),
FOREIGN KEY(roomname) REFERENCES room(roomname),
FOREIGN KEY(name) REFERENCES guest(name)
);
I am trying to write a query to find the guests who reserved EVERY "LakeView" room
I tried the following
SELECT g.name
FROM guest g, reservation r, room rr
WHERE rr.name = g.name
AND rr.roomname = "LakeView"
GROUP BY g.name
This does not seem to list out every room. How could I gix this?
Input:
insert into guest values ('Andrew', 1);
insert into guest values ('Jack', 4);
insert into guest values ('Jake', 4);
insert into room values ('LakeView', 'white', 10);
insert into room values ('BayView', 'blue', 4);
insert into reservation values ('Andrew', 'LakeView', 'Friday', 10,15);
insert into reservation values ('Jake', 'LakeView', 'Monday', 10,16);
insert into reservation values ('Jack', ' BayView', 'Tuesday', 11,15);
Desired output is
Andrew
Jake
try this:
Solution 1:
SELECT
guest.name
FROM guest INNER JOIN
reservation ON reservation.name = guest.name
INNER JOIN room ON reservation.roomname = room.roomname
WHERE reservation.roomname = "LakeView"
GROUP BY guest.name
Here I've highlighted your mistakes:
You tried to match rr.name with g.name. That means you are
matching roomname with guest name which you didn't want (so far I
guess).
Another mistake is you are only checking "LakeView" only in room
table entries. So other guests who haven't reserved LakeView room
might appear in the final result set. You also need to filter those
records from reservation table which have LakeView roomname.
Here's your query modified based on the above observations:
Solution 2:
SELECT g.name
FROM guest g, reservation r, room rr
WHERE r.name = g.name
AND rr.roomname = "LakeView"
AND r.roomname = "LakeView"
GROUP BY g.name;
N:B: Solution 1 is encouraged to use. Try to avoid implicit joins which are stated in solution 2.
I personally think the INNER JOIN is better, because it is more
readable. It shows better the relations between the table. You got
those relations in the join, and you do the filtering in the WHERE
clause. This separation makes the query more readable.
Have a look at this post.
if you using php-mysql then it will be help
$qry=mysql_query("select name from reservation where roomname='LakeView'");
while($result=mysql_fetch_array($qry)
{
echo $result['name'];
}
I'm assuming that the 'name' column in the reservation table is the name of the guest or guests. If this is true it sounds like you only need the reservation table for the purposes of this query, but if you wanted to combine them all anyway:
select
rv.name as Guest
from room as r
left join reservation as rv on rv.roomname = r.roomname
left join guest as g on g.name = rv.name
where
rv.roomname = 'LakeView'

Merge two databases, without duplicates, with FKs references [duplicate]

I have two mdb files.
I can also convert it to MySQL database, if necessary.
How can I merge these two different dbs to a single one?
The idea is to get all info form both dbs and merge into one, without duplicating any client.
The problem is that both bds have the same clients, and different ones, but the PKs of the clients aren't the same on them.
Every line has a unique field, I guess it can help somehow.
Any idea of how can I do that?
Select a UNION all columns except the PKs will give you only distinct rows:
insert into new_table (<non-pk columns>)
select <non-pk columns> from tableA
union
select <non-pk columns> from tableB
Note: union removes duplicates.
I would run an UPDATE to populate one of the tables w/ all info available.
Assuming the first table has all names that the second table has (that there are no name values in table 2 that are not in table 1) you should be able to run the following update to make the first table complete:
update tclient1 t join (select name,
max(tel) as tel_filled,
max(address) as add_filled
from (select name, tel, address
from tclient1
union all
select name, tel, address
from tclient2) x
group by name) x on t.name = x.name
set t.tel = x.tel_filled and t.address = x.add_filled;
See fiddle: http://sqlfiddle.com/#!2/3e7dc/1/0
Disable foreign keys (see here)
Update FK in the 2nd DB so make them unique, for instance:
update Client
set id_client = id_client + 100000000;
update History
set id_client = id_client + 100000000,
id_history = id_history + 10000000;
Enable FKs to check integrity
Export 2nd DB as SQL-inserts and execute it in the 1st DB.
Use backups, please.
Here is one approach that assumes that name is the match between the two rows. It just counts the numbers that are filled in and chooses the appropriate source. This version uses union all with a comparison in the where using >= or <:
insert into client(id, name, tel, address)
select id, name, tel, address
from db1.client c1
where ((id is not null) + (tel is not null) + (address is not null)) >=
(select (id is not null) + (tel is not null) + (address is not null)
from db2.client c2
where c1.name = c2.name
)
)
union all
select id, name, tel, address
from db2.client c2
where ((id is not null) + (tel is not null) + (address is not null)) >
(select (id is not null) + (tel is not null) + (address is not null)
from db1.client c1
where c2.name = c1.name
)
);
Note: the above version assumes that name is in both tables (as in the example in your question) and there are no duplicates. It can be easily modified if this isn't the case.

How to refer to a SELECT statement result table in MySQL?

I have two very simple questions:
what is name of a select statement result table in MySQL (a name that I can use in another select statement, for example in next line)?
how to naming that above table (in question 1)?
1- what is name of a select statement result table of in mysql?(a name that I can use it in another select statement(for example in next line))
Resultsets will not have any name unless you define an alias name while executing.
select * from department dept
In the above example dept is an alias name for department table.
2- how to naming that above table(in question 1)?
There could be cases where you select information from a single or multiple tables and join together. For that whole set you can define an alias.
select
emp_id, salary, commission,
( salary + commission ) as total_sal,
dept.dept_name as department_name
from employee emp, department dept
where emp.dept_no = dept.dept_no
For the above query you can give alias when used like:
select * from (
select
emp_id, salary, commission,
( salary + commission ) as total_sal,
dept.dept_name as department_name
from employee emp, department dept
where emp.dept_no = dept.dept_no
) as filtered_results
where
department_name in ( 'sales', 'marketing' )
Refer to:
MySQL: Schema Object Names
If I am correct, you wish to create a from a select command in mysql? This should work.
CREATE TABLE fishTypes (type VARCHAR(100)) SELECT type FROM allFish;
Is this the solution you are looking for? Here allFish might have the schema
(number INT, type VARCHAR(100))
it was found. I must use views.

What is the cleanest way of the following (MySQL)

I have a huge cities table containing around 3,000,000 rows. I needed to create a new column which contains the following line:
'City name, City name with accent, Country name'
Basic Schema is as follows:
city_id int
name varchar
status varchar
date_created int(11)
country_id int
accent_name varchar
city_country text
And there is the countries table which contains the contry_id and its name.
Now I figured out 2 ways to fill the city_country column.
Attempt 1:
delimiter //
CREATE FUNCTION getConcat(x INT(11))
RETURNS TEXT
READS SQL DATA
BEGIN
DECLARE var1 TEXT;
SELECT concat(CT.name, ', ', CT.accent_name, ', ', CR.name) AS Combined INTO var1 FROM `wp_City` AS CT LEFT JOIN `wp_Country` AS CR ON CR.country_id = CT.country_id WHERE CT.city_id = x;
RETURN var1;
END//
UPDATE `wp_City` SET `city_country`=(SELECT getConcat(city_id)) WHERE 1;
Attempt 2:
I created a new table containing just one column:
INSERT INTO `_myCity` (name, status, date_created, country_id, accent_name, lat, `long`, region, city_country)
SELECT c.name, c.status, c.date_created, c.country_id, c.accent_name, c.lat, c.long, c.region, _c.name
FROM `wp_City` as c inner join `wp_Country` _c on c.country_id = _c.country_id
Now the second way is much faster, but which is cleaner? The above will be executed only once, so the question is simply out of curiosity. If there are better ways of achieving this please do share!!
Thank you in advance.
If I were to do something like this I would rather go with a view that adds the column when needed (thus avoiding the additional overhead imposed by storing redundant data in the table on disk)