Most efficient way to get the data from database - php

So what i have is pretty simple.
I have 1 table
CategorieMain
like
CatMainid
CatMainName
and 1 table:
CategorieSub
like
CatId
CatName
CatMainId
'
What i want is :
A list with all the CatMainName's and under the names all the CatSubNames.
CatMainId1
all CatSubNames with CatMainId1
CatMainId2
all CatSubNames with CatMainId2
Etc Etc
Currently i use php to get the data like
SELECT * from Categoriemain
and in the while loop i do
SELECT * FROM CategorieSub WHERE CatMain id = $row['CatMainId']
But this is very inefficient because now if i have 10 CatMainId's i do 10 query's (for each one a while)
What is the most efficient way to get a list like this, i was thinking about putting it in arrays or something but i couldn't get it working?

SELECT * FROM Categoriemain
JOIN CategorieSub ON Categoriemain.CatMainid=CategorieSub.Catmainid
ORDER BY Categoriemain.CatMainid

Use one query:
SELECT Categoriemain.*, CategorieSub.CatSubNames FROM Categoriemain
JOIN CategorieSub ON Categoriemain.CatMainid=CategorieSub.Catmainid
Edited, removed GROUP BY
With this query, you don't need the while loop.
I have also added the CatSubNames to the output list of the query fields.

Related

how to get num row where object by other table use codeigniter

I have 2 tables. Consider tb_burung and tb_data.
This is the structure of tb_burung:
This is the structure of tb_data:
I want to get the number of rows of tb_data order id_burung for viewing on a page like this:
Not sure what exactly you want to achieve, but just try following sql:)
select t1.burung, count(t2.id_burung) as burungCnt
from tb_burung t1
left join tb_data t2 on t1.id_burung = t2.id_burung
group by t1.id_burung, t1.burung
First of all retrieve data from both tables individually. And then loop tb_burung table array and use array_filter out data from tb_data table array according to tb_burung id, use count function to get count of the filtered data. By doing like this, the process will be.
Two database query
3 loop, 3 array_filter and 3 count
u got the count.

Related Products SQL Query

I am trying to show something similar to related products on on my website. I have tested the following query, and I get no errors; but I get no results either.
<?php
$relatedStmt = $db->query("SELECT * FROM items WHERE tag LIKE id = 1 LIMIT 3");
?>
I also tried %1% and it displayed ALL the results, I assumed the code was thinking the query was just SELECT * FROM items.
The tags in the column are displayed in the following format: tagone two three four, so I am trying to display the products that have similar tags, hence why I used the LIKE clause.
Table screenshot
The current query is to relate with this query: SELECT * FROM items WHERE id = 1. So LIKE id = 1 is to find the tags that match this query to show the related products.
LIKE doesn't work the way you seem to expect. It's a character for character comparison, with wildcards, between the operands.
Of the mysql functions, closest to what you want is probably LOCATE or FIND_IN_SET. There are split solutions in other questions, e.g. "Can Mysql Split a column?" and "Split a MYSQL string from GROUP_CONCAT into an ( array, like, expression, list) that IN () can understand". However, even so there is no good way to compare the individual tags in your concatenated tag column with the individual tags of the other rows in your table.
Therefore, I think you'd be better off moving the tags into their own table with item_id as a foreign key. Then the solution is trivial (SQLFiddle):
-- Related Items
SELECT *
FROM items
WHERE id in (SELECT DISTINCT item_id
FROM tags t
JOIN (SELECT tag
FROM tags
WHERE item_id = 1
) t1 ON t1.tag = t.tag
WHERE item_id != 1
)
;
i am unsure about that id = 1 thing in your query but anyway you could try this: SELECT * FROM items WHERE tag LIKE '%search_this_tag%' LIMIT 3

Get an array of all columns starting with the same characters.

This is quite difficult to explain in the title, so I'll do my best here. Basically I have a column in a MySQL products table that contains rows like:
FEL10
FEL20
FEL30
PRO05
PRO07
PRO08
VAI12
VAI13
VAI14
These are the categories ("FEL","PRO","VAI") and a identification number of my products ("10", "20" and so on). I need an SQL select query that creates me a textual array like:
FEL*
PRO*
VAI*
With this array I need to create a listbox, that allows me to choose a category (regardless of the identification number). Once I choose a category, let's say PRO*, I will need to do the reverse action: print all the products info related to PRO05, PRO07 and PRO08.
How do you think you can achieve this? I have been trying using the DISTINCT statement but I need to filter only the first characters, otherwise it will be useless. I also tried the SUBSTRING() and LEFT() functions, but they seem not to be working (I get an SQL Syntax error).
--
Thanks for your help as always
What is wrong with?
SELECT distinct left(col, 3) as category FROM `table1`
MySQL LIKE to the resque:
SELECT col1 FROM table1 WHERE col1 LIKE 'FEL%';
This way you have to add all cases using OR.
Alternative - REGEXP:
SELECT col1 FROM table1 WHERE col1 REGEXP '(FEL|PRO|VAI).*'
Then it's just a matter of writing proper regex.
I would use extra col to group your items - to avoid such selecting altogether (which should be quite expensive on bigger dataset).
https://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_regexp
To get the list of the 3-letter codes use:
select distinct left(combicode, 3)
from mytable;
When a user selects one of the values use this to get all matching entries:
select *
from mytable
where combicode like concat(#category, '%');
(Aside from that: It's a bad idea to have concatenated values in one column. Why not have one column for the category and another for the product code? Then there would be no problem at all.)

SQL join into array for each table

I am joining two tables: customers and queries.
I am getting the full_name from the customers table and the description from the queries table.
I am wondering if it is possible to have the results of an SQL join split into arrays that correspond with the table the data came from? For example:
$STH = $DBH->prepare("SELECT queries.description, customers.full_name FROM queries INNER JOIN customers ON queries.customer_id = customers.id");
$STH->execute();
$queries = $STH->fetchAll();
At the moment, I can access my data like this: $queries[0]['description'] and $queries[0]['full_name']
However, my question is whether there is an easy way to get the data like so: $job[0]['query']['description'] and $job[0]['customer']['full_name'].
Just as teresko mentioned, I can't understand why you'd need that.
I can only imagine you want to see on the PHP code what are the table that contained the information.
Maybe you could do something like SELECT queries.description as queries_description, then your php code would look like $queries['queries_description']. Would it be enough?
You can loop through the results in PHP and convert it to the data structure you want, but you cannot (as far as I know) automatically group the data into arrays based on the source table. A (somewhat messy) alternative, using SQL is to use a multi-query and create a temp table from your original results, then select the results on a per-table basis, like so:
CREATE TEMPORARY TABLE q AS
(SELECT queries.description, customers.full_name FROM queries
INNER JOIN customers
ON queries.customer_id = customers.id
);
SELECT q.description FROM q;
SELECT q.full_name FROM q;
So, in those SELECT statements, you'll have to list all the columns that you want for each result. Then in PHP, you'll have to iterate over each resultset and put the data into arrays (or objects/whatever) as needed. Errr. A fetchAll will still not get you what you want, but a fetchAll on the first non-empty resultset will get you all the rows from queries and the 2nd will get you all the rows from customers

MySQL UNION SELECT until found?

Let's say I have table with column 'URL' whrere I store urls like this
one/two
one/two/three
alpha/omega
And I want to get data from database for specific url and if it is not found I remove the last part of url and search again:
Example:
I have url like one/two/three/four/five.
I do search for "one/two/three/four/five"
if not found search again for "one/two/three/four"
if not found search again for "one/two/three"
if not found search again for "one/two"
I would like to have something like:
SELECT * FROM db WHERE url=one/two/three/four/five
UNION
SELECT * FROM db WHERE url=one/two/three/four/five
UNION
SELECT * FROM db WHERE url=one/two/three/four
UNION
SELECT * FROM db WHERE url=one/two/three
UNION
SELECT * FROM db WHERE url=one/two
UNION
SELECT * FROM db WHERE url=one
but I want to stop searching if the row is found.
Is this possible or do I have to do it with separated queries.
Thanks for help.
I thing that this is the most elegant approach to your question. This statement is independent depth path and you don't need to split constant url in subsequent selects:
SELECT
*
FROM
db
WHERE
concat( 'one/two/three/four/five' , '/') like concat( url , '/%')
ORDER BY
LENGTH (url) desc
LIMIT 1
I have tested this query in MySQL, also you can check it! (in MSSQL syntax)
Just replace UNION with UNION ALL and add LIMIT 1 at the end.
P.S. UNION ALL would not make much difference in this particular example, but it is useful to know the difference: http://www.mysqlperformanceblog.com/2007/10/05/union-vs-union-all-performance/
Let's say I have table with column 'URL' whrere I store urls like this
one/two
one/two/three
alpha/omega
Don't do that, it's a horrible design and the proof is the problem you are having running such a simple query; store each URl on a DIFFERENT ROW. Read up on Normalization.
You could use a regexp to search in a single query, but it'll get you all rows:
SELECT * FROM db WHERE url REGEXP "^one((/two)|(/two/three)|(two/three/four)|(/two/three/four/five))?$"
so if you only want the results from the first WHERE you'll have to do multiple queries.
If you really want to have a single query and don't care about a little overhead in the search you could do
SELECT * FROM db WHERE url REGEXP "^one((/two)|(/two/three)|(two/three/four)|(/two/three/four/five))?$" ORDER BY length(url) DESC LIMIT 1
This will get you the first possible result only, but the query inside will have to get all possible results first -> less efficient, but more compact.
I hope this helps!

Categories