I want to join these two table but the join key of the second table is in a query string,
page table,
page_id url
1 a
2 c
3 d
system table,
system_id query
1 page_id=1&content=on&image=on
2 type=post&page_id=2&content=on
as you can see that page_id is part of the query string in system table.
so how can I join them like the standard joining table method below?
SELECT*
FROM page AS p
LEFT JOIN system AS s
ON p.page_id = s.page_id
EDIT:
I def can change the system table into something like this,
system_id page_id query
1 1 page_id=1&content=on&image=on
2 2 type=post&page_id=2&content=on
3 NULL type=page
But the reason why I don't want to do this is that the page_id is no need for many certain records. I don't want make a column with too many null.
I would definitely create columns for page_id,content, image and type (and get them indexed). Then the database would be much lighter and would work much faster.
Joining two tables without the common field and data type, is fundamentally wrong IMO.
I will suggest that you extract the page_id and insert it in the database and use a normal join to accomplish what you are searching for.
SO making the columns like
+------------+-----------+---------+
| system_id | page_id | query |
------------------------------------
Here is a snippet with which you are extract the page_id.
$query = 'page_id=1&content=on&image=on';
$queryParts = explode('&', $query);
$params = array();
foreach ($queryParts as $param) {
$item = explode('=', $param);
$params[$item[0]] = $item[1];
}
$page_id = $parems['page_id'];
Then you can go on with the insert and use simple join statement to solve your problem in a proper way.
Update:
Since you are able to change the schema to a feasible one. You dont need to worry about some rows having empty rows on this.
I guess you wanted something like this (MSSQL!):
DECLARE #query VARCHAR(50)
DECLARE #Lenght INT
DECLARE #PageID INT
SET #query = '4kkhknmnkpage_id=231&content=on&image=on'
SET #Lenght = PATINDEX('%&%', substring(#query,PATINDEX('%page_id=%', #query),50)) - 9
SET #PageID = CAST(SUBSTRING(#query,PATINDEX('%page_id=%', #query) + 8,#Lenght) AS INT)
SELECT #PageID -- you can do as you please now :)
OR:
SELECT*
FROM page AS p
LEFT JOIN (SELECT CAST(SUBSTRING(query,PATINDEX('%page_id=%', query) + 8,(PATINDEX('%&%', substring(query,PATINDEX('%page_id=%', query),50)) - 9)) AS INT) AS page_id
FROM system) AS s
ON p.page_id = s.page_id
-- Do as you please again :)
I guess what you really wanted was something like this (MYSQL!):
SET #query := '4kkhknmnkpage_id=231&content=on&image=on';
SET #Lenght := POSITION('&' IN (SUBSTR(#query,POSITION('page_id=' IN #query),50))) - 9;
SET #PageID := CAST(SUBSTR(#query,POSITION('page_id=' IN #query) + 8,#Lenght) AS SIGNED );
SELECT #PageID
OR
SELECT*
FROM page AS p
LEFT JOIN (SELECT CAST(SUBSTR(query,POSITION('page_id=' IN query) + 8,(POSITION('&' IN (SUBSTR(query,POSITION('page_id=' IN query),50))) - 9)) AS SIGNED) AS pageID
FROM system) AS s
ON p.page_id = s.pageID
Related
I need to execute these two queries from php, is there a way to merge them together in a single query or I have to use a stored procedure?
SET #rn=0;
UPDATE `nl_emails` SET `row_num`=(#rn:=#rn+1);
Thanks in advance
It doesn't look like it is possible. We could create #rn in the query but it will be local and the value will be lost from one row to another.
Here is another way of doing the what I believe you want to do.
create table nl_emails (id int not null primary key ,row_num int);
insert into nl_emails values(10,10),(20,20),(30,30);
with cte as(
select id, row_num,
row_number() over (order by id)rn
from nl_emails)
update nl_emails join cte on nl_emails.id = cte.id
set nl_emails.row_num = rn;
select * from nl_emails;
id | row_num
-: | ------:
10 | 1
20 | 2
30 | 3
db<>fiddle here
So as question marked with php tag, you can use PHP PDO solution:
<?php
$sql = "SET #rn = 0;
UPDATE nl_emails SET row_num = (#rn:=coalesce(#rn, 0) + 1);";
$pdo->exec($sql);
Test PHP PDO online
You can make in one direct query, but you have to check the performance.
Use:
UPDATE `nl_emails` n1
INNER JOIN (
SELECT (#row_number:=#row_number + 1) AS num,
id
FROM nl_emails, (SELECT #row_number:=0) AS t
) as t1 on n1.id=t1.id
SET n1.`row_num`=t1.num;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=bf7d4a9243eed3c3e3aeb934846294b7
The key part is the cross join used
SELECT (#row_number:=#row_number + 1) AS num,
id
FROM nl_emails, (SELECT #row_number:=0) AS t
;
I'm very new with SQL and need assistance on how I can accomplish this task using the correct query.
I have 2 tables that I need to use. Table "TB1" has:
id Name
1 bob
2 blow
3 joe
table "TB2" has:
compid property
1 bob
2 blow
I am trying to get which compid is missing in "TB2" and insert it from "TB1"
the query I am doing is:
SELECT id, name from TB1, TB2 where id <> compid
what I get is 2 ouputs of Id 1, and 2, and 3 outputs from id 3. by using php:
for($i=0;$i <= mysql_num_rows($comp)-1; $i++)
{
echo mysql_result($comp, $i, 0)."<br>";
}
and I expected the ouput 3 but instead got this:
1
1
2
2
3
3
3
I understand its comparing all the rows within the table but is there a way to achieve what I am looking for?
Thanks for your time.
You are performing an implicit Cartesian JOIN which results in every row against every other row. You need to specify what attribute JOINs the two tables.
Using implicit syntax (not recommended):
SELECT id, name
FROM TB1, TB2
WHERE id <> compid
AND TB1.Name = TB2.property <-- Column join
Using explicit syntax:
SELECT id, name
FROM TB1
JOIN TB2
ON TB2.property = TB1.Name <-- Column join
WHERE id <> compid
To accomplish your goal you would need something along the lines of:
SELECT TB1.id, TB1.name
FROM TB1
LEFT JOIN TB2
ON TB2.property = TB1.Name
WHERE TB2.compid IS NULL
See it in action
It's best practice to always alias the columns you select to prevent ambiguity.
To select it you can do:
SELECT *
FROM TB1
WHERE id NOT IN (
SELECT compid
FROM TB2
);
I have table (about 80'000 rows), looks like
id, parentId, col1, col2, col3...
1, null, 'A', 'B', 'C'
2, 1, ...
3, 1, ...
4, null, ...
5, 4, ...
(one level parent - child only)
and I need get all dependent rows -
SELECT ...
FROM table
WHERE id = :id OR parentId = :id OR id IN (
SELECT parentId
FROM table
WHERE id = :id
)
but why this request working slowly instead 2 request - if I get parentId on php first?
$t = executeQuery('SELECT parentId FROM table WHERE id = :Id;', $id);
if ($t) {
$id = $t;
}
$t = executeQuery('SELECT * FROM table WHERE id = :id OR parentId = :id ORDER BY id;', $id);
PS: max depends rows < 70
PPS:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY product ALL PRIMARY,parentId NULL NULL NULL 73415 Using where
2 DEPENDENT SUBQUERY product const PRIMARY,parentId PRIMARY 4 const 1
Change the IN for an equal =
SELECT ...
FROM table
WHERE id = :id OR parentId = :id OR id = (
SELECT parentId
FROM table
WHERE id = :id
)
or change it to a join:
SELECT ...
FROM table
inner join (
SELECT parentId
FROM table
WHERE id = :id
) s on s.parentID = table.id or s.parentID = table.parentID
Well, in the first case, MySQL need to create an intermediate result, store it in memory and then iterate over it to find all the relevant id in the table. In the second way, assuming you correctly created an index on id and parent id, it simply go straigth to the index, find the relevant rows, and send you back the result immediately.
UNION works faster for this case
this allows first query to user UNION INDEX and second just uses inner join, then merges results.
SELECT *
FROM `table`
WHERE id = :id OR parentId = :id
UNION
SELECT t1.*
FROM `table` t1 JOIN `table` t2 ON t2.parentId = t1.id AND t2.id = :id
An EXPLAIN might shed some more light on the problem for you.
Look into EXISTS, or rewriting your query as a JOIN.
It's a long shot but in first case you have "IN" statement of the WHERE part of the query. Maybe MySQL tries to optimize the query as if there would be multiple options and in the second case there is no IN part, so the compiled query is more straight forward for the database - thus utilizing the indexes in better manner.
Basically for 2 queries on the same connection the overhead of performing the queries should be minimal and irelevant in this case. Also subqueries in general are not very optimizable by the query parser. Try using JOIN instead (if possible).
I have a query of a mysql database that joins two tables. In the first table it just pulls records based on an id. For the second table, there may or may not be matches based on a value in the first table. I want to get matches if there are any, otherwise, presumably those values of the resulting record set are empty.
The query seems to produce the right number of records. However, when I try to access values of some variables that should be present, I am not getting anything, either because I may be calling them the wrong name or they are not in recordset somehow. I am a bit fuzzy on mysql queries so would greatly appreciate any advice..
Table 1 parks
id | name | stateid
Table 2 parksvisited
id | visited | parkid | userid
PHP script
$sql = "SELECT *
FROM `parks` p
LEFT JOIN `parksvisited` pv
ON p.id = pv.parkid
WHERE p.stateid = '44'"
run query...
while($row = mysql_fetch_array($res))
{
if ($row['visited'] == 1) {
$visited = 1; }
else {
$visited = 0; }
Visited
}
Basically, I get stateid but I am not getting p.id or visited. It could be I am naming them wrong or possibly they are getting left out of results somehow... Thanks for any suggestions.
p.id is probably missing because each of p.id and pv.id are going to get returned as id, not as p.id or pv.id. Try this instead:
SELECT p.id pid,
p.*,
pv.id pvid,
pv.*
FROM `parks` p
LEFT JOIN `parksvisited` pv
ON p.id = pv.parkid
WHERE p.stateid = '44'
It also doesn't look like you're selecting anything from pv in your original query, just p. See if this new query takes care of visited as well. And make sure to refer to pid as $row['pid'], not $row['p.id'].
I'm trying to join two tables. The first table has a list of 11 items which are 'site_names' with an auto id field of 'id'. The second table that I want to connect has an auto id field of 'desc_id' and another field of 'descriptions'. This second table currently has 3 rows of data that I want displayed only for id 1 in table 1.
So, I want to accomplish is to connect the first site in table one with an id of '1' to the entire second table.
I can't seem to figure out how connect only the first entry(id=1) in table 1 to all the rows in table 2 (tb.1->id->1 to tbl.2->desc_id->1,2,3).
I hope that made sense. Any help would be great. Thanks
Try:
select site_name, descriptions
from table_1
inner join table_2
on 1 = 1
where table_1.site_id = 1
This should join give you what you want.
OK - based on the comment, I'm guessing what you want is:
site1 | desc1 | desc2 | desc3
all on one row. This is a bit trickier - particularly if you want it to remain open to an arbitrary number of descriptions. For just 3 (or, really, any limited subset, but as the number goes up, it gets ugly), you could do:
select site_name, t2.desc, t3.desc, t4.desc
from table_1
inner join table_2 t2
on t2.desc_id = 1
inner join table_2 t3
on t3.desc_id = 2
inner join table_2 t4
on t4.desc_id = 3
where site_id = 1
This kind of stuff is highly irregular though. It seems to me like something about your schema is probably not quite right to generate this sort of requirement.
Here is the query:
<?php
$mysql = new mysqli('localhost', 'root', 'root') or die('counld not connect');
$result = $mysql->query("SELECT ajax_demo.explore.site_name, anthony1.property.descriptions FROM ajax_demo.explore INNER JOIN anthony1.property ON ajax_demo.explore.id = anthony1.property.desc_id") or die($mysql->error);
if($result)
{
while($row = $result->fetch_object())
{
$id = $row->id;
$siteName = $row->site_name;
$siteDescription = $row->site_description;
echo "$siteName";
echo "$siteDescription";
}
}
?>
I may be missing something here, but it sounds to me like you need to add a foreign key to the Site table. If I understand your question correctly, your tables should look something like this:
Site
- SiteID
- DescriptionID
- SiteName
Description
- DescriptionID
- Description
Then your query to get Sites and their associated Descriptions would look like this:
SELECT
s.SiteName,
d.Description
FROM
Site s INNER JOIN Description d
ON s.DescriptionID = d.DescriptionID
This table structure assumes that multiple Sites share single Descriptions (as per your posted question).