Arrange rows based on given values in Laravel Eloquent - php

So I have these fields in my directors table
id, name, position, summary, deleted
This table has the following records
1 | John Doe | President | Some text | 0
2 | Mary Doe | Vice President | Some text | 0
3 | Hannah Doe | Treasurer | Some text | 0
4 | Ann Doe | Board | Some text | 0
5 | Mark Doe | Board| Some text | 0
6 | Johnny Doe | Secretary | Some text | 0
As of now, I can get them by using this code
$directors = Director::where('deleted',0)->get();
But how can I arrange based on my preferred values, this should arrange like this.
President, Vice President, Secretary, Treasurer, Board and if the position is blank this will be below the records of Board Position
1 | John Doe | President | Some text | 0
2 | Mary Doe | Vice President | Some text | 0
6 | Johnny Doe | Secretary | Some text | 0
3 | Hannah Doe | Treasurer | Some text | 0
4 | Ann Doe | Board | Some text | 0
5 | Mark Doe | Board| Some text | 0

The query will be like this
SELECT *
FROM `directors`
WHERE `deleted` = '0'
ORDER BY CASE position
WHEN "President" THEN 1
WHEN "Vice President" THEN 2
WHEN "Secretary" THEN 3
WHEN "Treasurer" THEN 4
WHEN "Board" THEN 5
ELSE 6 END, position;
Eloquent version;
return Director::where('deleted', 0)
->orderBy(
DB::raw(
'CASE position
WHEN "President" THEN 1
WHEN "Vice President" THEN 2
WHEN "Secretary" THEN 3
WHEN "Treasurer" THEN 4
WHEN "Board" THEN 5
ELSE 6
END, position'
)
)
->get();

If your database is small enough, and you are not against doing the sort in laravel after the query, as it may get slow with massive data, then here is one way to do it using the collection method sort().
$sortOrder = array_flip(['President', 'Vice President', 'Secretary', 'Treasurer', 'Board', '']);
$directors = Director::where('deleted',0)
->get()
->sort(function($prev,$next)use($sortOrder){
// Note: Flip $prev and $next around on this next line for opposite order
return $sortOrder[$prev->position] <=> $sortOrder[$next->position];
});

Related

PHP / SQL - Get sum of another column

I have two tables in my MySQL database. One is called players and the other table is called worlds. Each player has a "level" and a "world" column. What I want to achieve is to fill up the columns in the table world based on the column values from table players. I want to first of all get the sum of players on that world and also an average of their levels.
My tables look like this:
Table: Players
+-------+-------+--------+----------+-------+--------------+---------+--------+
| id | name | sex | vocation | level | achievements | world | online |
+-------+-------+--------+----------+-------+--------------+---------+--------+
| 24471 | John | Male | None | 92 | 3 | Antica | 1 |
| 24493 | Bob | Male | None | 76 | 19 | Amera | 0 |
| 24535 | Sam | Male | None | 75 | 0 | Antica | 0 |
| 24574 | Sarah | Female | None | 78 | 23 | Beneva | 1 |
| 24673 | Carl | Male | None | 75 | 10 | Belobra | 1 |
+-------+-------+--------+----------+-------+--------------+---------+--------+
Table: Worlds
+----+---------+---------+--------+--------+----------+---------------+--------------+
| id | name | players | online | avglvl | totalexp | location | pvp |
+----+---------+---------+--------+--------+----------+---------------+--------------+
| 1 | Amera | 0 | 0 | 0 | 0 | North America | Open PvP |
| 2 | Antica | 0 | 0 | 0 | 0 | Europe | Open PvP |
| 3 | Astera | 0 | 0 | 0 | 0 | North America | Optional PvP |
| 4 | Belobra | 0 | 0 | 0 | 0 | South America | Optional PvP |
| 5 | Beneva | 0 | 0 | 0 | 0 | Europe | Optional PvP |
+----+---------+---------+--------+--------+----------+---------------+--------------+
So for example, we can see that the players John and Sam have the world Antica. Therefore, Antica should have the value "2" under the player column in the table world. But only John is online on Antica. So the world Antica should have the value "1" under the column "online" in the table "world". And so on. I also want their average level on that world.
How can I achieve this with PHP by making an SQL query?
First I need to get all the world names (I think?) and loop through them. And then get the following details for each world:
Player amount
Online amount
Average level amount
And then make an update in to worlds table with those values..
You can summarize the data as:
select world, count(*) as players, sum(online) as online, avg(level) as avglevel
from players
group by world;
You can incorporate this into an update:
update worlds w join
(select world, count(*) as players, sum(online) as online, avg(level) as avglevel
from players
group by world
) p
on w.world = p.world
set w.players = p.player,
w.online = p.online,
w.avglevel = p.avglevel;
I don't think maintaining a separate table like this is a good idea. After all, you can always just query players to get this information. Also the two systems can quickly get out-of-date, so the data is inconsistent. You would fix that by using triggers, but that adds complexity to the system. In general, a simple query is quite sufficient.

MySQL JOIN and SUBSELECT CONCAT

As a developer, I know a good DB guy is worth their weight in gold. I often find myself using seriously inefficient ways to tackle non critical problems, but in this current case, I need speed over 'just make it work'. I won't even show what I've done so far as it's so embarrassing, but lets just say that I had sub queries within my main PHP while loop. Sorry.
I have several tables that I need to join together for a json request to an indexing engine (Apache SOLR).
tbl_contacts
+----+--------------+---------------+
| ID | FirstName | LastName |
+----+--------------+---------------+
| 1 | Joe | Blogs |
+----+--------------+---------------+
| 2 | Jane | Baker |
+----+--------------+---------------+
| 3 | John | Doe |
+----+--------------+---------------+
tbl_attributes_map
+----+--------------+---------------+
| ID | ContactID | AttributeID |
+----+--------------+---------------+
| 1 | 1 | 1 |
+----+--------------+---------------+
| 2 | 1 | 3 |
+----+--------------+---------------+
| 3 | 2 | 2 |
+----+--------------+---------------+
tbl_attributes
+----+---------------+---------------+
| ID | AttributeType | Attribute |
+----+---------------+---------------+
| 1 | Lower | Shoe |
+----+---------------+---------------+
| 2 | Upper | T-Shirt |
+----+---------------+---------------+
| 3 | Upper | Vest |
+----+---------------+---------------+
tbl_notes
+----+---------------+---------------+
| ID | ContactID | Note |
+----+---------------+---------------+
| 1 | 1 | Big feet |
+----+---------------+---------------+
| 2 | 2 | Showoff |
+----+---------------+---------------+
| 3 | 2 | Sweaty |
+----+---------------+---------------+
tbl_appointment
+----+---------------+---------------+--------------------+-------------------+
| ID | ContactID | Location | TimeFrom | TimeTo |
+----+---------------+---------------+--------------------+-------------------+
| 1 | 1 | Big Ben | 2015-12-16 08:00:00|2015-12-16 08:30:00|
+----+---------------+---------------+--------------------+-------------------+
| 1 | 2 | London | 2015-12-17 10:00:00|2015-12-17 11:00:00|
+----+---------------+---------------+--------------------+-------------------+
| 1 | 2 | New York | 2015-12-16 12:00:00|2015-12-16 12:30:00|
+----+---------------+---------------+--------------------+-------------------+
I need to run a query which essentially allows me to print an array structure such as:
Array(
[FirstName] => Joe
[LastName] => Blogs
[Upper] => Array(
Vest
)
[Lower] => Array(
Shoe
)
[Notes] => Array(
Big Feet
)
[Location] => Array(
Big Ben
)
[ApptFrom] => Array(
2015-12-16 08:00:00
)
[ApptTo] => Array(
2015-12-16 08:30:00
)
If I can get to a stage where I can run a query to get the following output, I can run a delimiter to implode on the fields that I need to build an array for. EG:
+----+------------+-----------+---------+---------+-----------------+-------------------+-----------------------------------------+-----------------------------------------+
| ID | FirstName | LastName | Upper | Lower | Notes | Location | ApptFrom | ApptTo |
+----+------------+-----------+---------+---------+-----------------+-------------------+-----------------------------------------+-----------------------------------------+
| 2 | Jane | Baker | T-Shirt | | Show off,Sweaty | London,New York | 2015-12-17 10:00:00,2015-12-16 12:00:00 | 2015-12-17 11:00:00,2015-12-16 12:30:00 |
+----+------------+-----------+---------+---------+-----------------+-------------------+-----------------------------------------+-----------------------------------------+
My script currently works, but at a high performance penalty. It takes around 3 hours to churn through 80,000 contacts :-/
Thanks in advance.
I have exactly similar situation when I start indexing Elasticsearch (use Apache Lucene as SOLR) 50 million of data, now it only take me couple of hours I think what you can do are following:
put explain on your query to see if your query are using the proper index
try to use more sub select instead of join because mysql have problem to select with index for million of data (you can use force index maybe)
start muti-thread to do your indexing

How to search for higher values

I have tables:
City:
id | name
1 | New York
2 | Amsterdam
3 | Paris
4 | London
Trip:
id | name
1 | aaaa // New York --> Paris --> London
2 | bbbb // London --> Paris --> Amsterdam
3 | cccc // London --> New York --> Amsterdam --> Paris
4 | dddd // Paris --> London
5 | eeee // Amsterdam --> London
TripDetails:
id | tripId | cityId| order
1 | 1 | 1 | 1
2 | 1 | 3 | 2
3 | 1 | 4 | 3
4 | 2 | 4 | 1
5 | 2 | 3 | 2
6 | 2 | 2 | 3
7 | 3 | 4 | 1
8 | 3 | 1 | 2
9 | 3 | 2 | 3
10 | 3 | 3 | 4
11 | 4 | 3 | 1
12 | 4 | 4 | 2
13 | 5 | 2 | 1
14 | 5 | 4 | 2
Now i would like find cities by city using trips.
For example if i get Amsterdam then i would like receive Paris (Trip ID = 3) and London (Trip ID = 5). NOT New York because in Trip 3 New York is before Amsterdam.
Other example:
If i get New York then i should receive all cities - Paris (Trip 1), London (Trip 1) and Amsterdam (Trip 3).
If i get Paris then i should receive only London and Amsterdam.
So i have for Paris (ID: 3):
SELECT * FROM "City"
LEFT JOIN "TripDetails" ON City.id = TripDetails.cityId
WHERE TripDetails.cityId = 3
AND ????
How can i do it?
I can change the whole structure of the database if necessary. I use PHP and MySQL.
Try something like this. This example is for New York (city id = 1) :
SQL Fiddle
Query 1:
SELECT distinct city.name
FROM tripDetails td1
INNER JOIN tripDetails td2 ON td1.tripId = td2.tripId AND
td2.order > td1.order
INNER JOIN city ON td2.cityId = city.id
INNER JOIN trip ON td2.tripId = trip.id
WHERE td1.cityID = 1
Results:
| NAME |
|-----------|
| Paris |
| London |
| Amsterdam |

mysql query that outputs a table of data showing count

I have researched this and have not found the answer, so I thought someone here could shed some light. I'm trying to create a table of data returned showing the number of games picked for each user grouped by week numbers.
Database structure:
id | user | team | week_number
----+---------+-----------+-------------
1 | john | eagles | 1
2 | john | saints | 1
3 | harry | patriots | 1
4 | frank | cowboys | 1
5 | john | falcons | 2
6 | frank | cardinals| 2
Desired output:
week_number | frank | harry | john
------------+-------+-------+-------
1 | 1 | 1 | 2
2 | 1 | 0 | 1
I'll be using PHP to display the output.
The alternative to your desired output could be:
WEEK_NUMBER USER GAMES
1 frank 1
1 harry 1
1 john 2
2 frank 1
2 john 1
If this output could work for you, then you can run the following query:
select week_number,user,count(team) as games from table
group by week_number,user;
After banging my head in the wall, I got enlightenment and got the query finally. ;)
You could run this to achieve your desired output:
SELECT T.week_number,
IFNULL(SUM((CASE WHEN T.user = 'frank' THEN T.games END)),0) frank,
IFNULL(SUM((CASE WHEN T.user = 'harry' THEN T.games END)),0) harry,
IFNULL(SUM((CASE WHEN T.user = 'john' THEN T.games END)),0) john
FROM (select week_number,user,count(team) as games from table_name group by week_number,user) as T
GROUP BY week_number
DEMO

Binary Tree Using PHP & MySQL that creates 5 children and 25 grandchildren from registered members

Am working on a project that needs to create children and grandchildren using a root ID
It works in this way
user_1 registers himself, he(user_1) also registers 2, 3, 4, 5, 6 and have total(maximum) of 5 children
user_2 registers 7, 8, 9, 10, 11
user_3 registers 12, 13, 14, 15, 16
and so on
ON user_1's profile a tree table lists out his children and from his children,
the grandchildren he has from each of the registered children is also displayed.
1
----------------------------------------------------------------------
| | | | |
2 3 4 5 6
--------------- --------------- --------------- ------------ --------------
| | | | | | | | | | | | | | | | | | | | | | | | |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
The User_ID's would not necessarily be in order but just an example
Then also, USER 1 would see the total of children and grandchildren he has
The maximum of Children = 5, grandchildren = 20 == (25)
I have created a table like this
id | name | password | totalfamily | grandparent | parent_id
---------------------------------------------------------------
I would want the table to be hold info like this the one below
id | name | password | totalfamily | grandparent | parent_id
1 jon ****** NULL NULL
2 mel ****** NULL 1
3 al ****** NULL 1
4 me ****** 1 3
if there is need for new table structure to make it work, that will be ok too.
I have done the procedures for registration(including checking for the parent_id and grandparent_id) and the logging in
But am in a fix concerning how to QUERY the database to help me list out the names like a tree structure to show the children and the grandchildren
I know it needs complex querying statements to execute
I am in urgent need of solving this(hope it doesn't break the rules) as I have spent days reading Hierarchical data structuring tutorials for my Mysql+PHP yet none seems easy to be heading my direction.
Help anyone???
Thanks in advance.
I have just created table with id,name parent_id
+----+--------+-----------+
| id | name | parent_id |
+----+--------+-----------+
| 1 | one | NULL |
| 2 | two | 1 |
| 3 | three | 1 |
| 4 | four | 2 |
| 5 | five | 2 |
| 6 | six | 2 |
| 7 | seven | 2 |
| 8 | eight | 3 |
| 9 | nine | 3 |
| 10 | ten | 3 |
| 11 | eleven | 3 |
+----+--------+-----------+
and when user 1 want to get all the child. Query will like this
select * from users where parent_id in(select id from users where parent_id = 1) or parent_id = 1;
I think it may help you
+----+--------+-----------+------------+
| id | name | parent_id |grandparentID
+----+--------+-----------+------------+
| 1 | one | NULL | NULL |
| 2 | two | 1 | NULL |
| 3 | three | 1 | 1 |
| 4 | four | 2 | 1 |
| 5 | five | 2 | 2 |
| 6 | six | 2 | 2 |
| 7 | seven | 2 | 2 |
| 8 | eight | 3 | 3 |
| 9 | nine | 3 | 2 |
| 10 | ten | 3 | 1 |
| 11 | eleven | 3 | 2 |
+-------------+-----------+------------+
That's how I factored it to be.
And in the page that lists the children out this is how I got it.
Normal_codes
|
---newman ---ukwangwa ---hello ---azonto
using the following codes
function display_tree() {
$result = $this->qry("SELECT * FROM users WHERE Parent='?' or Parent ='?';" ,
'in(select id from user_id from users where Parent = "'.$_SESSION['id'].'")', $_SESSION['id']);
//select * from users where parent_id in(select id from users where parent_id = 1) or parent_id = 1;
echo '<div align="center">'.$_SESSION['name'].'<br></div>';
echo '<div align="center">|</div>';
echo '<div align="center">';
while( $row=mysql_fetch_assoc($result)){
echo "\n\r---".$row['name'];
$result1 = $this->qry("SELECT * FROM users WHERE grandParent='?' or grandParent ='?';" ,
'in(select user_id from users where grandParent = "'.$_SESSION['id'].'")', $_SESSION['id']);
while( $row1 =mysql_fetch_assoc($result1)){
//echo "<br>--".$row1['name'];
}
};
echo '</div>';
}
anyone got an idea as to any HTML, Javascript/Jquery Code that can help me to list the children and grandchildren out in a tree form.
Normal_codes
|
---newman --- ukwangwa --- hello --- azonto
| | | |
n1 n2 n3 n4 n5 n1 n2 n3 n4 n5 h1 h2 h3 h4 h4 a1 a2 a3 a4 a5
The initials being the children registered by each of the five parents
Any PHP code to aid me in the querying will also be appreciated.

Categories