I have several categories that I need to store in a database and present them to users. Each one has a minimum of three to a maximum of four ranges. E.g.:
id | category_name | Range A | Range B | Range C | Range D
--------------------------------------------------------------------
1 | Category1 | 0 - 200 | 200 - 450 | 450 - 750 | 750+
2 | Category2 | 0 - 300 | 300 - 600 | 600+ |
3 | Category3 | 0 - 250 | 250 - 350 | 350 - 550 | 550+
When an user picks a category, he should then select a certain range that will be saved in the database.
name | category_id | category_range
------------------------------------------
niceuser30 | 2 | A
hellouser1 | 1 | B
Considering that:
ranges cannot have gaps between them (e.g. if range A goes from 100 to 200, range B must start from 200)
each range must start from 0
each range must be open ended (or half-open)
What would be the best design for a table to hold these values?
I was thinking of using something akin to this
id | category_name | range_a | range_b | range_c | range_d
-------------------------------------------------------------
1 | Category1 | 1500 | 3000 | 5000 | 5000
2 | Category2 | 500 | 1000 | 1000 |
and then elaborate the output before serving it to the user (if two ranges are equal the code sets the last one "ad infinitum", so the first one would be "0 - 1500, 1500 - 3000, 3000 - 5000, 5000+") but it seems dirty and prone to errors.
you could use 2 table e.g Ranges:
id | RangeName| Start | End | Range |
--------------------------------------------------------------------
1 | A | 0 | 1500 | 1500 |
2 | B | 1500 | 3000 | 1500 |
3 | C | 3000 | 4000 | 1000 |
....
and RangeCategories:
id | CategoryID|RangeId|
--------------------------------------------------------------------
1 | 1 | 1 |
2 | 1 | 2 |
3 | 2 | 3 |
4 | 2 | 1 |
.....
And of course you will also have your categories Table:
id | CategoryName|...
--------------------------------------------------------------------
1 | Category1 | ...
2 | Category2 | ...
3 | Category3 | ...
Related
I have a mySQL database table containing cellphones information like this:
ID Brand Model Price Type Size
==== ===== ===== ===== ====== ====
1 Apple A71 3128 A 40
2 Samsung B7C 3128 B 20
3 Apple ZX5 3128 A 30
4 Huawei Q32 2574 B 40
5 Apple A21 2574 A 25
6 Apple A71 3369 A 30
7 Samsung A71 7413 C 40
Now I want to create another table, that would contain counts for every possible combination of the parameters.
Params Count
============================================== =======
ALL 1000000
Brand(Apple) 20000
Brand(Apple,Samsung) 40000
Brand(Apple),Model(A71) 7100
Brand(Apple),Type(A) 6000
Brand(Apple),Model(A71,B7C),Type(A,B) 7
Model(A71) 12514
Model(A71,B7C) 26584
Model(A71),Type(A) 6521
Model(A71),Type(A,B) 8958
Model(A71),Type(A,B),Size(40) 85
And so on for every possible combination. I was thinking about creating a stored procedure (that i would execute periodically), that would perform queries with every existing condition like that, but I am a little stuck on how exactly should it look like. Or is there a better way how to do this?
Edit: the reason why I want to store information like this is to be able to show number of results in filter in client application, like in the picture.
I would like to create index on the Params column to be able to get the Count number for given hash instantly, improving performance.
I also tried querying and caching the values dynamically, but I want to try this approach as well, so I can compare which one is more effective.
This is how I am calculating the counts now:
SELECT COUNT(*) FROM products;
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple');
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple', 'Samsung');
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple') AND Model IN ('A71');
etc.
You can use a ROLLUP for this.
SELECT
model, type, size, COUNT(*)
FROM mytab
GROUP BY 1, 2, 3
WITH ROLLUP
With your sample data, we get the following:
| model | type | size | COUNT(*) |
| ----- | ---- | ---- | -------- |
| A21 | A | 25 | 1 |
| A21 | A | | 1 |
| A21 | | | 1 |
| A71 | A | 30 | 1 |
| A71 | A | 40 | 1 |
| A71 | A | | 2 |
| A71 | C | 40 | 1 |
| A71 | C | | 1 |
| A71 | | | 3 |
| B7C | B | 20 | 1 |
| B7C | B | | 1 |
| B7C | | | 1 |
| Q32 | B | 40 | 1 |
| Q32 | B | | 1 |
| Q32 | | | 1 |
| ZX5 | A | 30 | 1 |
| ZX5 | A | | 1 |
| ZX5 | | | 1 |
| | | | 7 |
The subtotals are present in the rows with null values in different columns, and the total is the last row where all group by columns are null.
I'm coding a website for a photographer and I'm currently working on gallery implimentation.
I need to be able to take a row from point n.a and move it to point n.b
Here's an example of the raw table:
|gallery_img |
|--------------------------|
| id | fk_gal | fk_img | o |
| | | | |
| 0 | 16 | 240 | 1 |
| 1 | 16 | 322 | 2 |
| 2 | 27 | 240 | 1 |
| 3 | 16 | 245 | 3 |
| 4 | 16 | 210 | 4 |
| 5 | 27 | 530 | 2 |
All fields are INT(11). 'id' Auto_increments. 'fk_gal' and 'fk_img' are linked to other, irrelevant, tables via FOREIGN_KEY.
Now, 'o' is the field I'm focusing on. It determines what order the images will be displayed on the website. This value needs to always be unique for each table. To clarify, If I only call one table, 'o' should be different in every row. However, if I call the entire table, 'o[0]' might reoccur a few times.
So here's what I need. Firstly, I'm only going to be running this function on only one gallery at a time so all visuals of the table from here on out are going to be filtered with 'SELECT * FROM gallery_img WHERE fk_gal = 16'.
I need to change 'o' from n to n2 which will effectively move it on the database.
|gallery_img |
|--------------------------|
| id | fk_gal | fk_img | o |
| | | | |
| 0 | 16 | 240 | 1 |
| | | | | <--
| 1 | 16 | 322 | 2 |+ |
| 3 | 16 | 245 | 3 |+ |
| 4 | 16 | 210 | 4 | --|
The code needs to move the desired row (in this example 'o=4') to 1 and simultaneously move all of the next rows down to prevent any reoccurrences.
Here's my code I have right now. I'm coding my MySql scripts via PHP.
I am using the $n variable here. It includes the following data:
$n = array(gallery_id,img_id,target_o);
sql("UPDATE gallery_img SET o = o + 1 ORDER BY o ASC LIMIT ". ($n[2] - 1) .", 18446744073709551615;");
sql("UPDATE gallery_img SET o = ". ($n[2] + 2) ." WHERE fk_img = $n[1] AND fk_gal = $n[0];");
The problem I'm having with this is that when I execute it I get one of these two outputs:
|gallery_img |
|--------------------------|
| id | fk_gal | fk_img | o |
| | | | |
| 0 | 16 | 240 | 1 |
| 4 | 16 | 210 | 1 | <-- Shouldn't be duplicate
| 1 | 16 | 322 | 2 |
| 3 | 16 | 245 | 3 |
|gallery_img |
|--------------------------|
| id | fk_gal | fk_img | o |
| | | | |
| 0 | 16 | 240 | 1 |
| 4 | 16 | 210 | 2 |
| 1 | 16 | 322 | 4 |-|
| 3 | 16 | 245 | 4 | |-- Shouldn't be duplicate
| 5 | 16 | 273 | 4 | |
| 6 | 16 | 14 | 4 |-|
A good way to think of it is as so:
UPDATE
If you have any questions please let me know!
Thanks ahead of time for your help!
So if you're wanting to change the row WHERE o=4 to o=1 then increment the number to be replaced and all greater numbers.
UPDATE gallery_img SET o = (o + 1) WHERE o >= 1
Then update the row that you want to be o=1:
UPDATE gallery_img SET o = 1 WHERE fk_img = something1 AND fk_gal = something2
Or if you only know the o use o=(4+1) since it changed in the last UPDATE:
UPDATE gallery_img SET o = 1 WHERE o = 5
Can I suggest a hack? For the column o don't use an integer number, but a DOUBLE PRECISION one.
It would be much easier to insert a row in between, just by averaging the values of the previous and next row. If you need to insert between 3 and 4, you can just insert a row with 3.5.
Of course, after some time (after 50 times at least) you would like to re-number those values, since a DOUBLE PRECISION has 53 bits for the mantissa.
i want to COUNT column less than with other column which if Quantity in Hand < Minimum Quantity and i should get the result = 5
Instead, i got the result = 3.
| stock_id | stock_qtyhand | stock_minQty |
| 1 | 60 | 100 |
| 2 | 29 | 58 |
| 3 | 12 | 20 |
| 4 | 5 | 35 |
| 5 | 30 | 67 |
What seems to be the problem?
rsLowStock.Open "SELECT COUNT(stock_id) AS LowStock FROM stock_general WHERE stock_qtyhand<stock_minQty",conn
I appreciate your help
I have 3 tables like the tables below
tbl_GasExpense
GID | Gas_Expense | Date_Occured
-----------------------------------
1 | 400 | 11/30/2014
2 | 500 | 11/30/2014
3 | 300 | 11/30/2014
tbl_Food Expense
FID | Food_Expense | Date_Occured
-----------------------------------
1 | 450 | 11/30/2014
2 | 250 | 11/30/2014
3 | 390 | 11/30/2014
tbl_Drink Expense
DID | Drink_Expense | Date_Occured
-----------------------------------
1 | 150 | 11/30/2014
2 | 250 | 11/30/2014
3 | 360 | 11/30/2014
and with those tables above, I want an output like this.
ID | Gas_Sum | Food_Sum | Drink_Sum | Date_Occured
-----------------------------------------------------------
1 | 1200 | 1090 | 760 | 11/30/2014
The values of the three tables from which are dated 11/30/2014 are summed in table four.
Using the IDs from the first three tables as foreign keys in the table 4 to establish a relation. Gas_Sum is a mask for GID, Food_Sum for FID, Drink_Sum for DID.
Thanks guys, but I already have my answer now after several trial and errors
.. it is something like this. but this is on my own code
SELECT o.eh_ID, SUM(o.others_amt) as 'OTHERS SUM'
FROM tbl_Others o
INNER JOIN tbl_ExpenseHead hd ON hd.eh_ID = o.eh_ID
GROUP BY o.eh_ID
i have a table 'house' with a house id, a table 'room' with a room id, and a relation table for those two tables
HOUSE
-----
1 | house1
2 | house2
3 | house3
4 | house4
5 | house5
ROOM
------
1 | kitchen
2 | bathroom
3 | garage
HOUSE_ROOMS
------------
id | house_id | room_id | size
=================================
1 | 1 | 1 | 200
2 | 1 | 2 | 300
3 | 2 | 1 | 400
4 | 2 | 2 | 500
5 | 3 | 1 | 500
6 | 4 | 2 | 600
7 | 5 | 1 | 400
8 | 5 | 5 | 300
I'm having trouble writing a query that returns an array of house id's by some combined conditions:
example: get all houses with a kitchen sized between 350 and 450 AND a bathroom sized between 450 and 550
-> result should be an array containing house2
anyone know how i should write this query?
Assuming all your IDs are fixed, the following quick query will work:
SELECT HOUSE_ID
FROM HOUSE_ROOMS
WHERE (ROOM_ID=2 AND SIZE>=450 AND SIZE<=550)
OR (ROOM_ID=1 AND SIZE>=350 AND SIZE<=450)
GROUP BY HOUSE_ID
HAVING COUNT(DISTINCT ROOM_ID)>1