Hey,
I'm having a sorting issue. I have the rows:
32
16
8
semifinals
finals
that i need to be sorted like that. The problem is they don't always appear in that order. Right now I'm using: ORDER BY ABS(roundOf) DESC and it's comming out:
32
16
8
finals
semifinals
Thanks.
There is no way to do this without storing an order number with that data. The words semifinals and finals do not hold any order data comparable to the numbers of course. Store this in an array in the order you need it or if it's stored in a relational db, use an order column.
Possible db table:
order | name | numberOfPlayers
1 | finals | 2
2 | semis | 4
...
Array:
$rounds = array[1] = 'finals';
etc.
rename your finals and semifinals into numbers.
Related
take the case you have 2 table, for example tbCostumers and tbOrders.
I would like to display a summary list with all costumers, related orders and display them with a paginator.
Doing a join I can extract costumers list and all orders for each costumer, the result is something like:
idCostumer | name | ... | idProduct | productName | price | ...
Where the first n columns are all equal if the costumer has more than 1 order. So I can have:
1 | will | ... | 12 | product1 | 123 | ...
2 | bill | ... | 23 | product2 | 321 | ...
2 | bill | ... | 24 | product3 | 231 | ...
And so on
I'm trying to use LIMIT to extract only n records and using them with a paginator.
First question: if a costumer has more than 1 order, with this query I'll see n records, equal in the first column (id, name, ... and other costumer info) but different at the end, where there are products info. Is this 'correct'? Is there another way to extract this informations?
Second question: if I do that and I use a LIMIT, I could "cut" the result table between 2 (or more) records that represent the same customer; so, for example in the small table above, if I limit with 2 the third row will be lost, even if it's part of the row above, because is just another order of the same costumer.
I would like to limit the number of different idCostumer, in order to take exactly n costumers, even if they appear more than 1 times in the result table. Something like n different idCostumer, no matter if they are repeated.
Is this possible?
I hope it's clear, it was not easy to explain what I would like to achieve :)
Thank you!
You might want to have something like this:
SELECT * FROM (
(SELECT * FROM tbCustomers LIMIT 3) AS c
INNER JOIN tbOrders AS o ON o.customer = c.idcustomer
);
You can substitute the first asterisk with named columns and only receive your desired columns in the order you prefer (ie: SELECT c.name, o.price FROM...) .
Hope this works for you!
EDIT: changing the value of the LIMIT clause changes the number of the picked customers, of course.
EDIT 2: As Alvaro Pointed out, you'll probably need an order clause in the tbCustomers query.
Currently we have have following combined different data i.e one with comma separated and one without comma separated in same table.
#1
id | values
------------
1 | 1,2,3
2 | 4,5,6
3 | 7,8,9
4 | 1
5 | 2
6 | 3
7 | 4
8 | 5
Let's say I want to search value 1 from the table and count it. Which is the most optimal way of querying for such kind of data structure ? Is it using :
WHERE value =
WHERE value LIKE
WHERE value IN
Or Do I need to change my database and have all values to be in same format ?
Any help or advice on best practices would be appreciated.
Never store multiple values in one column!
Please normalize your data. That makes it way easier to query and it is also faster and can make use of indexes.
I agree that normalizing your data is the way to go to get optimal performance. But not changing the schemma, you can't really use = because you may have multiple numbers. One way to count the number of occurrences for 1 in those comma separated values is using FIND_IN_SET():
SELECT SUM(CASE
WHEN FIND_IN_SET(1, `values`)
THEN 1
ELSE 0
END) AS count1
FROM tab1
sqlfiddle demo
This is an expansion of my original question located here:
How do I pull all rows from a table with one unique field and specific values for another field?
I have a table with two fields: user_id and skill_id.
I want to pull out all rows that have a skill_id of a certain number but I have a large number of skill_id's to search for (~30). I was using the self-join suggestion presented in the question linked above but with so many skills to look for, that query is proving extremely slow.
How can I look for a large number of skill_ids without bogging down the query?
EDIT:
Here's an example of what I'm looking for. Using the table below, I want to pull out all rows of users that have skill_id of 10 AND 11 AND 12, etc. (except I'd be looking for more like 30 skills at a time).
TABLE
user_id | skill_id
=====================
1 | 10
1 | 11
1 | 12
1 | 13
2 | 10
2 | 12
2 | 13
3 | 15
3 | 16
4 | 10
5 | 45
5 | 46
If I understand your question well, below query might help you. Assuming (user_id, skill_id) is UNIQUE or PK.
SELECT user_id
FROM tab
WHERE skill_id IN (30 entries)
GROUP BY user_id
HAVING SUM(skill_id IN (30 entries)) = 30;
You can test here. http://www.sqlfiddle.com/#!2/f73dfe/1/0
select user_id
from table
where skill_id IN (10,11,12...)
make suer skill_is is indexed
I have a database containing places, and I need to show distances from any place to other ones in my webpage. Having the distances stored somewhere will save lots of work (loading them should be easier than computing them anew). But how to save the square matrix of the distances? Creating a new column every time I insert a new row doesn't seem to be a good solution, but I didn't find any better solution (though I can think of workarounds such as computing some 10 or 20 nearest distances and assuming I will rarely need more).
What is optimal way to save square tables of variable (and growing) size in PHP/MySQL? Or is there no good solution and my (or some other) workaround is better?
Edit Note: As was mentioned in a comment, once you get enough places it may make more sense to just store long/lat values and calculate the distance on the fly based on those instead. However the solution explained here may still be relevant for other applications.
The best way to handle this would be with a pivot table, where each row has two place id's, and a distance value.
Now, since Distance A-B is the same as B-A, we only need to store each pairing once. We can do this by only ever storing a distance if the ID of A is less than B.
SETUP
First a places table to store your places
id | name
---+---------
1 | Place_A
2 | Place_B
3 | Place_C
4 | Place_D
Then a places_distances Pivot table:
place_id_1 | place_id_2 | distance
-----------+------------+----------
1 | 2 | 10.0
1 | 3 | 20.0
1 | 4 | 15.0
2 | 3 | 12.0
2 | 4 | 8.0
3 | 4 | 14.0
Note that pivot tables do not need their own ID field (though some may argue it's still good to have one sometimes). You will set up a unique key as follows (you'll want to look into the documentation for correct usage):
UNIQUE KEY `UNIQUE_placesDistances_primary`(`place_id_1`,`place_id_2`)
This ensures that you cannot have the same place/place paring in the table twice.
You will also want to make sure to set up foreign keys:
CONSTRAINT FOREIGN KEY `FK_placesDistances_place1` (`place_id_1`)
REFERENCES `places`(`id`),
CONSTRAINT FOREIGN KEY `FK_placesDistances_place2` (`place_id_2`)
REFERENCES `places`(`id`)
Which will ensure that you can only add entries for place you actually have defined in places. it also means (if you use the default foreign key behavior) that you can't delete a place if you have distance row referencing that place.
Usage Examples
Looking up the distance between two places
(Given two variables #id_1 as the id of the first place and #id_2 as the id of the second place)
SELECT `distance`
FROM `places_distances`
WHERE (`place_id_1` = #id_1 AND `place_id_2` = #id_2)
OR (`place_id_2` = #id_1 AND `place_id_11` = #id_2)
LIMIT 1;
We use the OR to account for the case where we try to look up distance 2 to 1 and not 1 to 2 - remember, we only store values where the first place's id is less than the second to avoid storing duplicates.
Inserting a new distance
(Given three variables #id_1 as the id of the first place and #id_2 as the id of the second place, and #distance being the distance)
INSERT `places_distances`(`place_id_1`,`place_id_2`,`distance`)
VALUES(LEAST(#id_1, #id_2),GREATEST(#id_1, #id_2), #distance)
We're using the built in comparison functions LEAST and GREATEST to help maintain our rule that we only store places where the first ID is less than the second, to avoid duplicates.
Showing a list of place names, sorted by their distance from furthest to closest
To get the original names from the places table to show up in our places_distances query we have to join them together. In this case LEFT JOIN is the best choice since we only care about what is in the places_distances table. For more info on MySQL joins check here.
SELECT
`p_1`.`name` AS `place_1`,
`p_2`.`name` AS `place_2`,
`distance`
FROM `places_distances`
LEFT JOIN `places` AS `p_1`
ON `distances`.`place_id_1` = `p_1`.`id`
LEFT JOIN `places` AS `p_2`
ON `distances`.`place_id_2` = `p_2`.`id`
ORDER BY `distance` DESC
Which should return a table like this:
place_id_1 | place_id_2 | distance
-----------+------------+----------
Place_A | Place_C | 20.0
Place_A | Place_D | 15.0
Place_C | Place_D | 14.0
Place_B | Place_C | 12.0
Place_A | Place_B | 10.0
Place_B | Place_D | 8.0
showing a table of places and their distances to a specific given place
This is a bit more tricky since we need to show the name in a row that is not our input place, but we can use another useful function IF(CONDITION,'TRUE_OUTPUT','FALSE_OUTPUT') to do that.
(#place_name being the variable containing the place name, in this case 'Place_B')
SELECT
IF(`p_1`.`name`=#place_name, `p_2`.`name`, `p_1`.`name`) AS `name`,
`distance`
FROM `places_distances`
LEFT JOIN `places` AS `p_1`
ON `distances`.`place_id_1` = `p_1`.`id`
LEFT JOIN `places` AS `p_2`
ON `distances`.`place_id_2` = `p_2`.`id`
WHERE `p_1`.`name` = #place_name OR `p_2`.`name` = #place_name
ORDER BY `distance` DESC
Which should return a table like this:
name | distance
--------+-----------
Place_C | 12.0
Place_A | 10.0
Place_D | 8.0
I would store the lat/long for all places and write a function to calculate distance between them with the lat/long information.
In this way, no need to calculate the distances for new places you want to add in you DB.
Moreover if you have lots of places, using a pivot table to store only the distances, you have to be aware that this table can grow very fast. As you need to cover all combinaisons of places.
For instance: for 1000 places you will have 1000 * 1000 - 1000 = 999000 rows in your table. Do the math for larger number but this table might contain a lot a rows depends on how many places you've got.
Break it into another table called "distance" that relates back to the original "place" table:
create table distance (place_id_1 int, place_id_2 int, distance int);
That is, for each place, calculate the distance for another place and save it in this new table.
You could create a new table with two columns as foreign keys for the locations and one column for the distance between them.
|place1 | place2 | distance
-+-------|--------|---------
|.... |..... | .....
Depends on how many locations you have, this table could grow very fast.
The simplest way is make another table which will contain two places id and the distance like
place1 place2 distance
a b 20
c d 30
in the time of fetching data just join it with place table.
I think something like this could do the job.
ORIGIN | CITY 1 | CITY 2 | CITY 3 | CITY 4 | CITY 5
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
CITY 1 0 20 40 20
CITY 5 10 50 20 0
CITY 3 10 0 10 40
You can easily get the distances to other places and the you don't need to store the names of the cities for each distance you know.
SELECT 'CITY 2' FROM DISTANCES WHERE ORIGIN='CITY 5'
I am working on an image processing project. I am using php for the GUI and matlab for the algorithm and Mysql as my database. I have 30,000 of images stored in the database for now. My matlab program will generate 3 arrays for each image containing 300 elements. So, my question is
Whether to save that arrays generated from matlab for all images in a single txt file or create a txt file for each image. Which method will be easier to retrieve datas and store into the database?
How hard it is to copy array form a txt file and saving it into the database? Is there any standard process for this?
The elements of the array must be retrieved for further computation. Can we use serialize and deserialize for this purpose?
I have to compare 2 array elements at a time and obtain a third array with the minimum values from both array. Eg A=[1 2 3 4] and B=[6 1 4 2] I have to compare each elements of this 2 array and generate a third array c=[1 1 3 2] that is comparing each elements of the array with its corresponding elements of the other array and storing the minimum element in the third array. This process is repeated with thousands of arrays comparing with 1 fixed array. Is there any php function to do this?
Any suggestions and help will be highly appreciable. Thank you.
The best solution in this case is to create a separate meta table that stores the data(arrays) that relates to your images.
Here's a simple example EER:
The combination of image_id (referencing foreign key), array, and index make up the primary key for the meta table.
I'm assuming you can safely represent the keys of your arrays as just 0-indexed, and all values of your arrays are also numbers (which is why all fields are of type INT, but if not, adjust the datatypes accordingly).
image_id represents the linked image_id.
array represents the specific array (you said up to 3 arrays, so values in this column would be anywhere from 1-3).
index is the numerical index in the array.
value is the value in the array paired with the index.
Example data in your meta table might look like:
image_id | array | index | value
------------------------------------------------------
256 | 1 | 0 | 5
256 | 1 | 1 | 9
256 | 1 | 2 | 4
256 | 1 | 3 | 23
256 | 1 | 4 | 1
256 | 2 | 0 | 9
256 | 2 | 1 | 15
256 | 2 | 2 | 8
256 | 2 | 3 | 19
256 | 2 | 4 | 11
In the above example data, we have two arrays (each represented by 1 and 2 in the array column) with 5 elements each (key represented in the index column, and value represented in the value column.
You can store however many arrays you want, with however many indexes you want.
You can also perform your needed array comparison calculation right in MySQL using GROUP BY. Here is how you can find the minimum value for each key across all arrays for image_id 256 (let's say there are 3 arrays):
SELECT index, MIN(value) AS minvalue
FROM image_meta
WHERE image_id = 256
GROUP BY index
Since a composite index is set up on (image_id, array, index), this should be extremely quick.
This design also allows you to have a variable number of indexes and arrays per image.
Reading through your problems, regardless of my comment, a relational database would be better for you, and if performance is not a big issue, then SQL would be the language to solve your issues best, not on the PHP level.
And yes, PHP has easy ways also to solve those problems, albeit not as easy as in SQL.