MySQL ORDER BY 'ENUM' type value - php

I'm having a table:
ID TYPE VALUE
1 phone 12345
2 fax 98753
3 address etc
...
the TYPE col is defined as ENUM with values: 'phone','fax','address'.
Now my query is:
$q = mysql_query(SELECT * FROM tbl ORDER BY id);
while(row = mysql_fetch_array($q)){
echo $row['type'] . "--->" . $row['value'];
}
The output is ordered by id, first line is phone, then it's fax and then it's address.
But I want the output be order by:
1- All address
2- All Phone
3- All fax
How I could achieve this?
Thanks for your help :-)

Try this query -
SELECT * FROM tbl
ORDER BY
CASE type
WHEN 'address' THEN 1
WHEN 'phone' THEN 2
WHEN 'fax' THEN 3
ELSE 4
END
Full example:
CREATE TABLE tbl (
id int(11) DEFAULT NULL,
type enum ('phone', 'fax', 'address') DEFAULT NULL,
value int(11) DEFAULT NULL
);
INSERT INTO test.tbl(id, type, value) VALUES
(1, 'phone', 11),
(2, 'fax', 22),
(3, 'address', 33),
(4, 'fax', 44),
(5, 'address', 55);
SELECT * FROM tbl
ORDER BY
CASE type
WHEN 'address' THEN 1
WHEN 'phone' THEN 2
WHEN 'fax' THEN 3
ELSE 4
END;
+------+---------+-------+
| id | type | value |
+------+---------+-------+
| 3 | address | 33 |
| 5 | address | 55 |
| 1 | phone | 11 |
| 2 | fax | 22 |
| 4 | fax | 44 |
+------+---------+-------+

SELECT A.*,
case ID
when 3 then 1
when 2 then 3
when 1 then 2
else 4 end as myorder
FROM tbl A
ORDER BY myOrder
Alternatively update the enum to list the Number first on the type field such as 01.Address, 02.Phone, 03.Fax.. then your order by type instead of ID. The 2nd approach makes it pretty easy to add up to 99 types without having to change code (just data) if you add another type later using the first approach, you have to edit the SQL...
The first approach uses a case statement to generate a calculated column at run time. This new column contains the correct order by substituting the IDs for the order you want (it doesn't change the IDs, it simply defines them in the order you want) and then orders by this new calculated column.
$q = mysql_query(SELECT A.*, case ID when 3 then 1 when 2 then 3 when 1 then 2 else 4 end as myorder FROM tbl A ORDER BY myOrder);
The second approach involves changing the data in the enum such that it is preceeded by a number which defines the sort you want. Thus if you change the SQL in your sort to sort by Type instead of ID, it would then work.
$q = mysql_query(SELECT * FROM tbl ORDER BY Type);

Related

Build a multidimensional PHP array out of MySQL table data linked by values in one column

I am using a Wordpress plugin (Advanced CF7 DB). It puts the results of the contact form into the MySQL database so it can be displayed on the front end of the website.
There are two tables with data like this.
Table 1:
id | created
-------------------------------
1 | 2020-09-21 13:04:09
2 | 2020-09-22 13:04:09
3 | 2020-09-23 13:04:09
4 | 2020-09-24 13:04:09
5 | 2020-09-25 13:04:09
Table 2:
data_id| name | value
-------------------------------
1 | fname | Joe
1 | sname | Smith
1 | age | 19
1 | display | yes
1 | comment | Here is my comment
2 | fname | Jenny
2 | sname | Ford
2 | age | 20
2 | display | no
2 | comment | Here is my comment
3 | fname | Hazel
3 | sname | Brown
3 | age | 15
3 | display | yes
3 | comment | Here is my comment
The id in table 1 corresponds to the data_id in table 2.
I need to display the comment on the website in two separate lists (for people above and below 18), and only display comments where there is a row with 'name = display' and 'value = yes' for the corresponding data_id.
Example:
Comments from people under 15:
ID: 3
Name: Hazel Brown
Comment: Here is my comment
Comments from people over 18
ID: 1
Name: Joe Smith
Comment: Here is my comment
Would the best approach to be to put the information into a multidimensional PHP array where I can manipulate it, or should I try to use MySQL to get the information in the format I need it?
I'm not sure why your table is formatted that way in the first place, but you could devise your row values into columns first, then using HAVING clause to filter by your criteria:
Here's a sample:
SELECT
t2.dataid,
MAX(IF(t2.name = 'fname', t2.value, NULL)) AS `fname`,
MAX(IF(t2.name = 'sname', t2.value, NULL)) AS `sname`,
MAX(IF(t2.name = 'age', t2.value, NULL)) AS `age`,
MAX(IF(t2.name = 'display', t2.value, NULL)) AS `display`,
MAX(IF(t2.name = 'comment', t2.value, NULL)) AS `comment`,
t1.created
FROM table2 t2
JOIN table1 t1 ON t2.dataid = t1.id
GROUP BY t2.dataid, t1.created
HAVING display = 'yes' AND age >= 18
# age <= 15 whatever your condition for age
Right after that it's just a matter of fetching it. Sidenote: I'm not a wordpress guru, but it's fairly straightforward, execute the query -> fetch the results, loop them in your markup.
global $wpdb;
$query = '<your query here>';
$results = $wpdb->get_results($query);
foreach ($results as $row) {
echo 'ID: ', $row->dataid;
echo 'Name: ', $row->fname, ' ', $row->sname;
echo 'Comment: ', $row->comment;
}
It's just a sample, you can squeeze in your markup html whichever you like.

Join multiple tables and search parameters

I have database with 2 tables, 1 for storing customers Id and for customer informations. The second table is ordered with key/value because I need to store undefined values without needing to alter customers table.
Table structure
table customers:
=================
id | status
=================
table customers_info:
=======================================
id | id_customer | key | value
=======================================
Content example:
table customers:
=================
id | status
1 | 1
2 | 1
3 | 1
==================
table customers_info
=======================================
id | id_customer | key | value
1 | 1 | name| Doe
2 | 1 | age | 25
3 | 1 | city| NY
4 | 2 | name| Smith
5 | 2 | age | 26
6 | 3 | age | 30
=======================================
I simply query my tables with
SELECT ci.id_customer AS CustomerId,
MAX(CASE WHEN ci.key = 'name' THEN ci.value ELSE '' END) AS CustomerName,
MAX(CASE WHEN ci.key = 'age' THEN ci.value ELSE '' END) AS CustomerAge,
MAX(CASE WHEN ci.key = 'city' THEN ci.value ELSE '' END) AS CustomerCity
FROM customers_info ci
GROUP BY ci.id_customer
ORDER BY ci.id_customer;
I can get all customers, but cannot query with age for parameter for example, I tried try search every customer with age 25 but with this query I can't get all values for the customer...
SELECT ci.id_customer AS CustomerId,
MAX(CASE WHEN ci.key = 'name' THEN ci.value ELSE '' END) AS CustomerName,
MAX(CASE WHEN ci.key = 'age' THEN ci.value ELSE '' END) AS CustomerAge,
MAX(CASE WHEN ci.key = 'city' THEN ci.value ELSE '' END) AS CustomerCity
FROM customers_info ci
LEFT JOIN customers_info on customers_info.age = '25'
GROUP BY ci.id_customer
ORDER BY ci.id_customer;
I would like to get
=======================================
id_customer | name | age | city
1 | Doe | 25 | NY
=======================================
I am not sure that the way you are doing this the best way (I am not sure I would use maximums to do this, nor do I think I would create the tables in the way you are doing it - since in this case you are performing several extra operations in order to have the key value table that you are using) - but here is my go -
First, my create statements:
create database CustomerLinkQuestion;
use CustomerLinkQuestion;
create table customers (
id int,
status int
);
create table customer_info (
id int,
id_customer int,
k varchar(255),
v varchar(255)
);
For whatever reason (and this may be because I don't use MySQL all that much) key and value didn't work (probably reserved) so I used k and v for your key and value segments.
The core concept is that you are going to have to use a sub-query of some sort or a view (a view would be better) -
select * From (
SELECT ci.id_customer AS CustomerId,
MAX(CASE WHEN ci.k = 'name' THEN ci.v ELSE '' END) AS CustomerName,
MAX(CASE WHEN ci.k = 'age' THEN ci.v ELSE '' END) AS CustomerAge,
MAX(CASE WHEN ci.k = 'city' THEN ci.v ELSE '' END) AS CustomerCity
FROM customer_info ci
GROUP BY ci.id_customer
ORDER BY ci.id_customer) as sub
where sub.CustomerAge = 25
the inside (the part in parenthesis and called sub) is exactly what you posted (except - for whatever reason on my test server I used "customer" and not "customers"). Then the sub-query, then the where clause cutting down the sub-query.
Again - I would strongly suggest you look at your schema and design since it seems like you are trying to create a code table for something that it simply doesn't make sense. You will end up with a fixed number of fields in the customer table, each tied to a specific customer. When you are doing what you are doing here, you are performing more database operations that are simply not necessary.
Best of luck!
Aleksei

Know last X field value

I have a database with this table
+------+---------------------+-------------+
| id | key | value |
+------+---------------------+-------------+
| 152 | incidencia_0_fecha | 20150306 |
| 158 | incidencia_1_fecha | 20150307 |
| 234 | incidencia_2_fecha | 20150309 |
| . | ...... | ........ |
| n | incidencia_N_fecha | date_value |
+------+---------------------+-------------+
And I want to know what is the last key (N its dinamic and i don't know his last value). In this table the last must be incidencia_2_fecha.
How can i do it?
Thanks
You can easily get the number in the string using two REPLACES.
SELECT MAX(
REPLACE(REPLACE(`key`, 'incidencia_', ''), '_fecha', '')
)
FROM mytable
If the values in the id column are strictly increasing, you can do this:
SELECT key FROM your_table WHERE id = (SELECT MAX(id) FROM your_table);
EDIT 1:
If the table is quite large, you should make sure that there's an index on the id column. Otherwise the query could take a long time to run.
EDIT 2:
Another option, if the value column contains the date at the time the record was inserted (and is indexed), would be to do the above query, but replace id with value, i.e.
SELECT key FROM your_table WHERE value = (SELECT MAX(value) FROM your_table);
First fetch record in desc
SELECT key from tbl_name ORDER BY id DESC LIMIT 0,1

Retrieve Value From Database & Replace With Text

I am currently performing this statement:
SELECT * FROM b_tasks WHERE CREATED_DATE BETWEEN '$from' AND '$to' AND GROUP_ID=13 ORDER BY ID DESC
This returns:
Responsible ID | Title | Date Created
2 | Job 1 | 2013/09/20
4 | Job 2 | 2013/09/20
The responsible_id represents an actual name in number form. For example resonsible_id 2 is actually Bob Taylor and responsible_id 4 is Andrew Thompson. So what I'd like to do is replace the numbers in the table with their name, so where its 2, display Bob Taylor and where its 4 display Andrew Thompson.
I am currently printing these answers using PHP.
. $row['RESPONSIBLE_ID'] .
Should I be using an IF statement, if responsible_id=2 display Bob and so on?
Any ideas?
UPDATE:
There is a User Table yes, this reads:
Table name: b_users
ID | NAME | LAST_NAME
1 | Andy | Champ
2 | Bob | Taylor
3 | Katie | Gillo
4 | Andrew | Thompson
Obviously, ID in this table corresponds with responsible_id in the other table. Would I be able to join these in the same statement above?
do you have a table that you can join to? if not, you can use CASE
CASE WHEN Responsible_ID = 2 THEN 'Bob Taylor'
WHEN Responsible_ID = 4 THEN 'Andrew Thompson'
ELSE Responsible_ID
END AS Responsible_ID
SELECT a.*,
CONCAT(b.Name, ' ', b.Last_Name) Fullname
FROM b_tasks a
INNER JOIN b_users b
ON a.Responsible_ID = b.ID
WHERE CREATED_DATE BETWEEN '$from' AND '$to' AND GROUP_ID=13
ORDER BY ID DESC
and call $row['Fullname']
try this
UPDATE `table` SET `id` = CASE
WHEN id = 1 THEN 'value1'
WHEN id = 2 THEN 'value2'
WHEN id = 3 THEN 'value3'
ELSE `id`
END
WHERE id in (1,2,3)

Mysql query In QUERY with only 1 result for each in id

Please excuse the vagueness of my title, I really don't know how to succinctly write what I am trying to do.
I have a table with
name - str
item_id - int
position - int
name item_id position
| 6asd | 17 | 1 |
| asdf | 3 | 1 |
| asdf | 3 | 2 |
| asdf | 3 | 3 |
| asdf | 3 | 4 |
I am trying to use an IN query on a list of item_ids and only return 1 row per item and that should be the row with the lowest position.
select name, item_id, position from my_table
WHERE item_id IN (17, 3) AND name != '';
This returns all rows for the item_id when I am only trying to return the lowest position. Naturally I looked at ORDER_BY and LIMIT but my query only is done on the whole results set not on each id individually.
ORDER BY position ASC LIMIT 1
Has anyone tried to do this before?? any help would be greatly appreciated. Do I need to use a subselect somehow?
Use MIN() that is available.
SELECT name, item_id, MIN(position)
FROM my_table
WHERE item_id IN (17, 3) AND name != ''
GROUP BY item_id;
I think you might be looking for the MIN() function.
MySQL MIN function is used to find out the record with minimum value among a record set.
Try something along these lines:
"SELECT name, item_id, MIN(position)
FROM my_table
WHERE item_id IN (17, 3) AND name != ''
GROUP BY item_id";

Categories