I got this MYSQL table:
+---------------+
|ID|OID| mpn |
+--+---+--------+
|1 | 1 | 12345 |
|2 | 1 | 54321 |
|3 | 2 | 78912 |
|4 | 2 | 12431 |
|5 | 2 | 78787 |
|6 | 3 | 14565 |
.................
Now I want to set the values [mpn] for each [OID] in an array.
Something like this:
$oid1 = array([mpn1], [mpn2])
$oid2 = array([mpn1], [mpn2], [mpn3])......
Or just manage to output the [mpn] referring to [OID]. So, I want to get every MPN referring to OID=1, for example. So, how do I select those values out of the table?
Here used COALESCE() and GROUP_CONCAT Functions.
The GROUP_CONCAT function concatenates strings from a group into one string with various options.
The COALESCE function evaluates the arguments in order and returns the current value of the first expression that initially does not evaluate to NULL.
select t.OID,COALESCE( GROUP_CONCAT( t.mpn) , '' ) as mpn
from tableName t
group by t.OID
If mpn have any null value then you can fill up this null value with any String or null. That u want to do.
I think you want group_concat():
select oid, group_concat(mpn) as mpns
from t
group by oid;
This creates the list of mon as a comma-delimited list which you can parse in php.
Related
I have a table like this:
-- mytable
+----+------------+
| id | value |
+----+------------+
| 1 | one,ten |
| 2 | nine,two |
| 3 | five, one |
+----+------------+
The value of value column is always made of two parts which are combined with ,. Now I want to select them in two separated column like this:
-- expected result:
+----+-------+------+
| id | val1 | val2 |
+----+-------+------+
| 1 | one | ten |
| 2 | nine | two |
| 3 | five | one |
+----+-------+------+
How can I do that?
I can do that by PHP like this:
-- query
SELECT id, value FROM mytable
-- then
$vals = explode(",", $rows['value']);
foreach($vals as $val){
//do stuff
}
But I want to know is that possible to I do that in mysql?
For this you can use the function INSTR() to find the position of the comma and then use LEFT() and RIGHT() to split these into the two columns you need, as below:
SELECT id
,LEFT(value,INSTR(value,',')-1) AS val1
,RIGHT(value,CHAR_LENGTH(value)-INSTR(value,',')-1) AS val2
FROM mytable
It would be done by using SUBSTRING_INDEX(string,delimiter,count) like this:
SELECT id,
SUBSTRING_INDEX(value,',', 1) as val1,
SUBSTRING_INDEX(value,',', -1) as val2
FROM mytable
so here is my query
SELECT
bia_clients.name "Builder Name",
bia_panels.value "Name on Panel",
bia_sizes.size "Size",
bia_panels.sign_id "Sign Locations",
count(bia_panels.sign_id) AS "Number of Panels",
revenue_sharing AS "Amount Per Panel",
count(bia_panels.sign_id) * revenue_sharing "Return to City"
FROM bia_panels
JOIN bia_projects ON bia_panels.project_id = bia_projects.id
JOIN bia_clients ON bia_clients.id = bia_projects.client_id
JOIN bia_sizes on bia_sizes.id = bia_panels.size_id
JOIN bia_prices ON bia_prices.size_id=bia_sizes.id
WHERE LEFT(bia_panels.sign_id, 3) = 042
group by bia_panels.value with rollup;
and this code works to grab my columns and totals as expected
here
Builder Name | Name on Panel | Size | Sign Locations | Number of Panels | Amount Per Panel | Return to City
______________________________________________________________________________________________________________________________________
HAMPTON INN | Hampton Inn | Single | 042182 | 2 | 19.00 | 38.00
BIA | Model Homes | Single | 042301N | 1 | 19.00 | 19.00
Richmond | American | Single | 042092 | 3 | 19.00 | 57.00
Standard Pacific| Standard Pacific| Single | 042102 | 7 | 19.00 | 133.00
Standard Pacific| NULL | Single | 042102 | 13 | 19.00 | 247.00
what i am having trouble with is getting the Sign Locations field i would like it to list each of the items that build the total for that column
for example i would lilke my column to look like this
... | Sign Locations | Number of Panels | ...
..._________________________________________________...
| 042182, 042117 | 2 |
| 042301N | 1 |
| 042092, 042097, 042005 | 3
...
And as far as the formatting i can use some COALESCE statements to clean up the null lines i am not worried about that
but my strugle is how to make the Sign Locations field list all of the locations
i have tried to use a nested select statement (SELECT id from table where) but it still will only return the first item
any ideas?
Try using GROUP_CONCAT()
From the docs:
GROUP_CONCAT(expr)
This function returns a string result with the concatenated non-NULL
values from a group. It returns NULL if there are no non-NULL values.
In your case:
...
GROUP_CONCAT(bia_panels.sign_id) AS "Sign Locations",
...
I have 3 table:
tblNames:
| id | firstname | lastname |
+------+---------------+--------------+
| 1 | John | Smith |
tblJosbs (this table accepts multiple checkbox value at the same time):
| id | jobs |
+------+-----------------------+
| 1 | Nurse |
+------+-----------------------+
| 2 | Call Center Agent |
+------+-----------------------+
| 3 | Police |
tblNamesJobs (this table is used to JOIN the other 2 tables):
| id | name_id | jobs_id |
+------+-------------+-------------+
| 1 | 1 | 1 |
+------+-------------+-------------+
| 2 | 1 | 2 |
+------+-------------+-------------+
| 3 | 1 | 3 |
All is fine but can someone show me the INSERT statement for the 3rd table I should use to when I will add new information?
For example add record that John Smith is a Call Center Agent
insert into tblNamesJobs (name_id,jobs_id )
values (
select id from tblNames where
firstname='John'
and lastname='Smith' limit 1
,
select id from tblJosbs where jobs='Call Center Agent' limit 1
);
If you are already depending on tauto increment..you can get the lastinserid, depending on your adapter.
eg. mysql_insert_id
for PDO we can use --PDO::lastInsertId.
so you will have id's of earlier inserted tables, that you can save in the new one.
INSERT INTO tblNamesJobs (name_id, jobs_id) VALUES (XXXX,YYYY)
That is assuming the table's id is auto-incrementing.
It should be noted that both the name_id and jobs_id columns in the "joiner" table should be foreign keys to the respective columns in the other table.
Edit - Valex's answer goes into more detail about what to do if you don't already have the id values.
If possible, I would recommend using some sort of framework that would handle the "joiner" table for you.
Let's say I have this table:
|user_id | first_name | last_name |
----------------------------------|
| 0 | joe | smith |
| 1 | bob | jones |
| 2 | joe | black |
| 3 | mary | jeane |
| 4 | peter | parker |
How would I go about selecting the contents of the rows which correspond to the user_id's 1, 2 and 3? I want to use these rows later to display their contents in a list to the user.
Try this:
select user_id,first_name,last_name
from your_table_name
where user_id in (1,2,3);
Replace your_table_name with the actual table name.
Place the comma separated column names that you want as output right after select keyword.
in clause is used to select between multiple values.
So in your case, query would look some how like this:
select user_id, first_name, last_name
from table_name
where user_id in (1,2,3);
Preface: Yes i realize this is bad design, but i can't change this.
Question
I have a customers table, and within that a field 'products'. Here is an example of what is in a sample customers products field:
36;40;362
Each of those numbers reference a record from the products table. I'm trying to do a
(SELECT group_concat(productName) from products where productID=???)
but am having trouble with the delimiters. I know how to remove the semi colons, and have tried 'where INSTR' or IN but am having no luck.
Is the best approach to return the whole field to PHP and then explode / parse there?
You can use FIND_IN_SET function in MySQL.
You just need to replace semicolons with a comma and the use it in your query:
SELECT group_concat(productName)
FROM products
WHERE FIND_IN_SET(productID, ???) > 0
Just remember that ??? should be comma-separated!
Like you said, this isn't the way to do it. But since it's an imperfect world:
Assuming a database structure like so:
+-PRODUCTS---------+ +-CUSTOMERS---------+------------+
| ID | productName | | ID | customerName | productIDs |
+----+-------------+ +----+--------------+------------+
| 1 | Foo | | 1 | Alice | 1;2 |
+----+-------------+ +----+--------------+------------+
| 2 | Bar | | 2 | Bob | 2;3 |
+----+-------------+ +----+--------------+------------+
| 3 | Baz | | 3 | Charlie | |
+----+-------------+ +----+--------------+------------+
Then a query like this:
SELECT customers.*,
GROUP_CONCAT(products.id) AS ids,
GROUP_CONCAT(productName) AS names
FROM customers
LEFT JOIN products
ON FIND_IN_SET(products.id, REPLACE(productIDs, ";", ","))
GROUP BY customers.id
Would return:
+-RESULT------------+------------+-----+---------+
| ID | customerName | productIDs | ids | names |
+----+--------------+------------+-----+---------+
| 1 | Alice | 1;2 | 1,2 | Foo,Bar |
+----+--------------+------------+-----+---------+
| 2 | Bob | 2;3 | 1,2 | Bar,Baz |
+----+--------------+------------+-----+---------+
| 3 | Charlie | | 1,2 | NULL |
+----+--------------+------------+-----+---------+
FIND_IN_SET( search_value, comma_separated_list ) searches for the value in the given comma separated string. So, you need to replace the semicolons with commas, which is obviously what REPLACE() does. The return value of this function is the position where it found the first match, so for example:
SELECT FIND_IN_SET(3, '1,3,5') = 2
SELECT FIND_IN_SET(5, '1,3,5') = 3
SELECT FIND_IN_SET(7, '1,3,5') = NULL