I'm currently running into a problem where I am required to pivot many rows into a single row, defined by a specific key. I know the GROUP_CONCAT functionality and am using that currently, but I would like to avoid having to use explode in PHP after fetching my results. My table looks like this:
----------------------------------
| primary_id | key_value | value |
----------------------------------
| 1 | my_key_1 | val_1 |
| 1 | my_key_2 | val_2 |
| 1 | my_key_3 | val_3 |
| 2 | my_key_4 | val_4 |
| 2 | my_key_5 | val_5 |
----------------------------------
And I would like to build a MySQL-Query that presents this exactly like this for primary id 1 and primary id 2:
-----------------------------------------------
| primary_id | my_key_1 | my_key_2 | my_key_3 |
-----------------------------------------------
| 1 | val_1 | val_2 | val_3 |
-----------------------------------------------
------------------------------------
| primary_id | my_key_4 | my_key_5 |
------------------------------------
| 2 | val_4 | val_5 |
------------------------------------
So I can retrieve the output as an array in PHP, with the form:
$output[1][my_key_1] = val_1
$output[1][my_key_2] = val_2
...
The GROUP_CONCAT functionality works, but it would be much nicer to just have the value in the form I needd it only using SQL.
Would appreciate any pointers, best regards.
Use a Pivot
select max(case (when key_value=my_key_1 then val_1 end)),
max(case (when key_value=my_key_2 then val_2 end)),
from...
etc...
Related
SAMPLE TABLE
TABLE FIRST_TABLE
| rid | requirements |
| 1 | 2x2 pic |
| 2 | valid id |
| 3 | 137 form |
| 4 | app form |
Second table
| id | applicant_id | rid | remarks |
| 1 | 1 | 1 | pass |
| 2 | 1 | 2 | pass |
| 3 | 2 | 1 | pass |
How to select all records from first table and show even the data is not exist on second table.
Result should be like this.
applicant_id | rid | remarks |
1 | 1 | pass |
1 | 2 | pass |
1 | 3 | null |
1 | 4 | null |
this is my sample code.
select requirements from first_table
left join second_table on first_table.rid = second_table.rid
where second_table.applicant_id = 1
group by first_table.rid
//result :
applicant_id | rid | remarks |
1 | 1 | pass |
1 | 2 | pass |
You just need to move the second_table.applicant_id = 1 to the join.
select requirements, first_table.rid, remarks
from first_table
left join second_table on
first_table.rid = second_table.rid and
second_table.applicant_id = 1
group by first_table.rid
http://sqlfiddle.com/#!9/a0cffdd/17
+------+---------+----------+
| id | uid | assessors|
+------+---------+----------+
| 1 | 1 | Volvo |
| 2 | 2 | kenitra |
| 3 | 3 | rabat |
| 4 | 3 | Fahad |
| 5 | 3 | John |
+------+---------+----------+
I want to fetch the data on the base of uid because i use a Inner join to fetch data from other table now i want to fetch and show all assesors on uid but i get this output
+---------+----------+
| uid | assessors|
| 1 | Volvo |
| 2 | kenitra |
| 3 | rabat |
Desired Output is:
+---------+----------+
| uid | assessors|
| 1 | Volvo |
| 2 | kenitra |
| 3 | rabat |
| 3 | Fahad |
| 3 | John |
my query is =
SELECT * FROM lego_activity_answers WHERE uid = $studentid;
$studentid comes from another table
If you want to get all data in the lego_activity table except for id, simply select the individual fields you want, instead of querying *
SELECT uid, assessors FROM lego_activity_answers WHERE uid = $studentid;
SELECT DISTINCT uid ,assessors FROM lego_activity_answers where uid=$studentid;
( this may not perform well at all in large tables )
I'm trying to use Eloquent to find the max value of a column on the last table of a multiple has-many relationship.
Given the following table structure.
Buildings
+----+---------------+
| id | building_name |
+----+---------------+
| 1 | Building 1 |
| 2 | Building 2 |
+----+---------------+
Rooms
+----+-----------+-------------+
| id | room_name | building_id |
+----+-----------+-------------+
| 1 | Room 1 | 1 |
| 2 | Room 2 | 1 |
| 3 | Room 3 | 2 |
+----+-----------+-------------+
maintenancelog
+----+-------------------+---------+---------------------+
| id | maintenance_value | room_id | timestamp |
+----+-------------------+---------+---------------------+
| 1 | Cleaned | 1 | 2015-09-06 00:54:59 |
| 2 | Cleaned | 1 | 2015-09-06 01:55:59 |
| 3 | Cleaned | 2 | 2015-09-06 02:56:59 |
| 4 | Cleaned | 2 | 2015-09-06 03:57:59 |
| 5 | Cleaned | 3 | 2015-09-06 04:58:59 |
| 6 | Cleaned | 3 | 2015-09-06 05:59:59 |
+----+-------------------+---------+---------------------+
I'd like to see if it's possible to generate an eloquent statement that would retrieve the building name, room name, and ONLY the LAST maintenance log date value.
The following works to give me a collection of ALL the values.
$buildings = Building::with('rooms.maintenancelog')->get();
but this errors out, and it looks like it's trying to call max(maintenancelog.timestamp) on the buildings table..
$buildings = Building::with('rooms.maintenancelog')->max('maintenancelog.timestamp')->get();
Error returned:
.....(SQL: select max(`maintenancelog`.`timestamp`) as aggregate from `buildings`)
Am I just asking too much from eloquent, and should I just use the basic query builder
Add the following relationship to the Rooms model...
public function latestMaintenance()
{
return $this->hasOne('App\Maintenancelog')->latest();
}
and change the Eloquent statement to..
$buildings = Building::with('rooms.latestMaintenance')->get();
referenced Getting just the latest value on a joined table with Eloquent
What's the most effective way to go about querying the table to output the results as shown?
Table:
+-----+----------+-----+
| PN | date | QTY |
+-----+----------+-----+
| AB1 | 01/12/14 | 4 |
| AB2 | 01/12/14 | 2 |
| AB3 | 01/12/14 | 7 |
| AB1 | 01/22/14 | 8 |
| AB3 | 01/25/14 | 3 |
| AB5 | 01/25/14 | 9 |
+-----+----------+-----+
Results:
+-----+----------+----------+----------+
| | 01/12/14 | 01/22/14 | 01/25/14 |
+-----+----------+----------+----------+
| AB1 | 4 | 8 | 0 |
| AB2 | 2 | 0 | 3 |
| AB5 | 7 | 0 | 9 |
+-----+----------+----------+----------+
What you want to do is called pivoting the data. It can be achieved in MySQL with some CASE statements and aggregate functions.
E.G.
SELECT PN,
SUM(CASE WHEN date='20141201' THEN qty END) AS day1Qty,
SUM(CASE WHEN date='20141202' THEN qty END) AS day2Qty
FROM table
GROUP BY PN
Of course you'll likely want to do something to dynamically handle the dates that are being aggregated so it isn't just a static list (unless that is what you're after).
See these answers for more info:
Pivot Table Using MySQL
MySQL pivot table
I have a table in mysql, let's call it foo and it has a limitied amount of columns.
| id | name | date |
--------------------------
| 1 | bar | 2012-05-08 |
| 2 | buba | 2012-05-09 |
My users can add records to the table foo_field (stuff like, code, description, time...).
| id | name |
--------------------
| 1 | code |
| 2 | description |
| 3 | time |
In the table foo_field_value the values for the user-defined fields are stored, like so:
| id | foo_id | foo_field_id | value |
------------------------------------------
| 1 | 1 | 1 | b |
| 2 | 1 | 2 | Lalalala |
| 3 | 1 | 3 | 12:00 |
| 1 | 2 | 1 | c |
| 2 | 2 | 2 | We are go |
| 3 | 2 | 3 | 14:00 |
Ideally, I'd want one query which would give me a result like
| id | name | date | code | description | time |
------------------------------------------------------
| 1 | bar | 2012-05-08 | b | Lalalala | 12:00 |
| 2 | buba | 2012-05-09 | c | We are go | 14:00 |
Is this even possible without doing an inner join on the foo_fields_value table for every foo_field (generating the query with PHP by doing another query first).
It's possible to do it in just one, and quite simple.
We are going to modify the foo_field table a bit, adding a column corresponding to the foo table's id column, which I assume is the primary key.
so now we have
* foo
|------|
| id |
| name |
| date |
|------|
* foo_field
|-------------|
| foo_id |
| code |
| description |
| time |
|-------------|
Which means we can add the extra fields with one simple query:
SELECT * FROM foo
LEFT JOIN foo_field ON foo.id = foo_field.foo_id
Which will give us a result set of
| id | name | date | foo_id | code | description | time |
|----+-------+------------+--------+--------+-------------+----------|
| 1 | asdw | 2012-05-16 | 1 | asdasd | asdasd | 15:03:41 |
| 2 | fdgfe | 2012-05-18 | 2 | asdas | asdas | 15:03:41 |
| 3 | asdw | 2012-05-16 | 3 | asdas | asdas | 15:03:52 |
| 4 | fdgfe | 2012-05-18 | 4 | asdasd | asdasd | 15:03:52 |
I am still not sure I surely understood your question. If you want to create truly dynamic values and datastructures, I suggest you save a serialized array into a TEXT field in your database, but I also suggest you to overlook your solution if this is the case; if you want your solution to be able to grow, you want to manage as strict structures as possible.
What you are looking for is a pivot query. And since you have dynamic fields that need to converted to columns, check this article here about making automatic pivot queries
http://www.artfulsoftware.com/infotree/queries.php#523