how to count the mysql data when match rules - php

I would like to do a show how many promotion code left function.
I already find out how to query the latest promotion. now i would like to show the code how many left.
Now I have 2 table,
this is t1.
+--------------+--------------------------+----------------------+
| id | name | description |
+--------------+--------------------------+----------------------+
| 1 | GG | GG is good |
| 2 | ABC DEFG | ABC DDDDD |
| 3 | CCARD | Gooooo |
+--------------+--------------------------+----------------------+
this is t2
+---------+------------+-------------------+------------------+
| id | kaid | code | timestamp |
+---------+------------+-------------------+------------------+
| 1 | 2 | ZZZZAAAAA | 123456789 |
| 2 | 2 | AAAZZADWWW | 123344444 |
| 3 | 1 | ASFASDFFFF | 123333333 |
| 4 | 2 | HHHHHFDFG | 123222222 |
| 5 | 1 | ASDASDADDDD | 123111111 |
| 6 | 1 | AAAAAAAA | |
| 7 | 1 | DGDFGDSFG | |
+---------+------------+-------------------+------------------+
I query the latest user get promotion code like this
$querylist = mysql_query("SELECT t2.*,t1.name FROM t2,t1 where t1.id = t2.kaid ORDER BY t2.timestamp desc limit 5");
while($rowlist = mysql_fetch_row($querylist)) {
$idlist[] = $rowlist['id'];
$user_list_latest[] = $rowlist;
}
After I loop query, I will get the data like this
1. GG
2. ABC DEFG
3. GG
4. ABC DEFG
5. ABC DEFG
Then I would like to show the count like this.
Hypothesis the count data is $countleft
1. GG (This promotion code only 2 left!)
2. ABC DEFG (This promotion code only 0 left!)
3. GG (This promotion code only 2 left!)
4. ABC DEFG (This promotion code only 0 left!)
5. ABC DEFG (This promotion code only 0 left!)
the number 2 and 0 is $countleft.
the t2 timestamp is means the user get the valid promotion code time. so the timestamp empty means nobody get yet.

Change your query to this and try
select name,balance from t1 join
(SELECT kaid,COUNT(ID) as balance FROM t2
WHERE isnull(timestamp) GROUP BY kaid)t3
on (kaid=t1.id) ORDER BY balance desc limit 5;
In the loop print every row and column(there is only two column for each row). It will give the answer.

Related

get table information using feching table in mysql stored procedure

Help....
I have 2 tables,
customers
id | registration_code | full_name
1 | A01 | ABC
2 | B01 | BCD
3 | C01 | CDE
4 | D01 | DEF
history_transaction
id | customer_id | transaction_date
1 | 1 | 2015-01-01
2 | 2 | 2015-01-01
3 | 3 | 2015-01-01
4 | 1 | 2015-01-02
5 | 3 | 2015-01-02
6 | 1 | 2015-01-03
I use PHP, and I want to get a customer list and transaction times between 2015-01-01 till 2015-01-03
the result should be
id | registration_code | full_name | n_trans
1 | A01 | ABC | 3
2 | B01 | BCD | 1
3 | C01 | CDE | 2
Please help. I want to use Store Procedure on MySQL, and I dont want to loop it in PHP.
To get the info you use a group by statement:
SELECT a.id,a.registration_code,a.full_name, COUNT(*) as n_trans
FROM customers a
INNER JOIN history_transaction b
ON a.id=b.customer_id
WHERE b.transaction_date BETWEEN "{start_date}" AND "{end_date}"
GROUP BY a.id,a.registration_code,a.full_name;
You can set start_date and end_date dynamically using mysqli (a php module for working with MySQL from php).
This is the way to create stored procedure in MySQL:
CREATE PROCEDURE find_transaction_detail()
BEGIN
SELECT a.id,a.registration_code,a.full_name, COUNT(*) as n_trans
FROM customers a
INNER JOIN history_transaction ON a.id=b.customer_id
WHERE b.transaction_date BETWEEN "{start_date}" AND "{end_date}"
GROUP BY a.id,a.registration_code,a.full_name;
END;
Way to find result:
CALL find_transaction_detail ();

MySQL MIN() limit by column

I have a MySQL table that is formatted as follows:
group_clue:
---------------------------------------------------
| id | group_id | clue_id | completed | run_order |
---------------------------------------------------
| 1 | 1 | 2 | 1 | 1 |
| 2 | 1 | 6 | 1 | 2 |
| 3 | 1 | 4 | 1 | 3 |
| 4 | 1 | 3 | 0 | 4 |
| 5 | 1 | 1 | 0 | 5 |
| 6 | 1 | 5 | 0 | 6 |
| 7 | 2 | 9 | 1 | 1 |
| 8 | 2 | 2 | 0 | 2 |
...
---------------------------------------------------
The data above in the group_clue is constructed such that each group_id has every clue_id at some run_order (ranging from 1 to the number of clue_ids and not repeating for a particular group).
First Question
I want to create a table showing the first clue_id for each group_id where completed = 0 when ordered by run_order (aliased as current_clue). Using the above example, this would give:
---------------------------
| group_id | current_clue |
---------------------------
| 1 | 3 |
| 2 | 2 |
---------------------------
My preliminary attempt is:
SELECT group_id, MIN(clue_id) as current_clue
FROM group_clue
WHERE completed = 0
GROUP BY group_id
However, this returns the same clue_id for each group_id.
Second Question
From the data in the first question, I would like to compose a final table where I GROUP_CONCAT() these results so that it contains every current_clue and each group_id that contains that current_clue. I would also like it ordered from those clues with the most group_ids to those with the fewest. An example resulting table is:
--------------------
| clue | group_ids |
--------------------
| 3 | 1,5,4,3 |
| 2 | 2,6 |
--------------------
I cannot figure out the ordering. My preliminary attempt is:
SELECT clue_id, GROUP_CONCAT(group_id)
FROM [resulting_table]
GROUP BY clue_id
ORDER BY [something]
Any help is appreciated: what queries would fit this scenario?
The first part of your question can be solved this way (it expects that run_order is unique per group):
SELECT t1.group_id,
t1.clue_id AS current_clue
FROM group_clue t1
INNER JOIN (SELECT group_id,
MIN(run_order) as run_order
FROM group_clue
WHERE completed = 0
GROUP BY group_id) t2 USING (group_id, run_order)
The logic of this query is pretty simple:
The inner query selects the pairs of group_id and the corresponding minimal value of run_order which has the completed = 0.
After that we join the original table to this set of pairs so that we could select the corresponding clue_id additionally.
You can sort by number of elements per group using
ORDER BY COUNT(*) DESC

Multiple select and condition by column

I am trying to figure out how to select an item from table by his column name p.e.
strucutre looks like this
table items
id | name | column_1 | column_2 | column_3 |
1 | nm1 | 1 | 4 | 7,8 |
2 | nm2 | 2,3 | 4 | 9 |
3 | nm3 | 3,1 | 4 | 7 |
table columns
id | c_name |
1 | cnm1 |
2 | cnm2 |
3 | cnm3 |
table column_values
id | c_id | value |
1 | 1 | abcd |
2 | 1 | cdbh |
3 | 1 | dsff |
4 | 2 | wewe |
5 | 2 | cgbh |
6 | 2 | cdlh |
7 | 3 | adbh |
8 | 3 | qdbh |
9 | 3 | pdbh |
So when I wanted to find "abcd" I tried
"SELECT a.* FROM items a, columns b, column_values c WHERE c.`value` LIKE '%abcd%' GROUP BY a.`id`"
but I knew this will find nothing without any conections so i went further
"SELECT a.* FROM items a, columns b, column_values c WHERE c.`value` LIKE '%abcd%' AND b.`id` = c.`c_id` GROUP BY a.`id`"
still no proper connection with item
and here is the problem there is a changing amount of columns and the name contains id of the column and value is set of ids of column values.
So i need to select item by his name which is "name+"column_id in column_values by FIND IN SET cause if i look for abcd it is id 1 and there are two items which have id 1 in column_1
item 1 and item 2
ALSO id of values are AI so there is not possibility of duplicate so there is no need to check of column_id to search in proper column in item table
it can work something like for from 0 - 30 p.e. and it will search in column_1, column_2 column_3 until 30 for id match

Selecting random triplicates (or more) from database

I have two tables:
Students Student_Grades
V------------------------V
+----+------+ +----+------------+---------+-------+
| id | name | | id | student_id | subject | grade |
+----+------+ +----+------------+---------+-------+
| 0 | Dave | | 0 | 0 | Math | 100 |
+----+------+ +----+------------+---------+-------+
| 1 | John | | 1 | 0 | Chem | 90 |
+----+------+ +----+------------+---------+-------+
| 2 | Kate | | 2 | 0 | CompSCI | 95 |
+----+------+ +----+------------+---------+-------+
| 3 | Mimi | | 3 | 1 | ELA | 98 |
+----+------+ +----+------------+---------+-------+
| 4 | 2 | Biology | 92 |
+----+------------+---------+-------+
| 5 | 2 | Chem | 94 |
+----+------------+---------+-------+
| 6 | 2 | Math | 98 |
+----+------------+---------+-------+
| 7 | 3 | Math | 100 |
+----+------------+---------+-------+
I would like to select all subjects and grades from a random student that is enrolled in more than three subjects. (Either Dave or Kate)
Students John and Mimi would not be even considered because they are not enrolled in three subjects.
I know I can achieve this with PHP but I would like this to be done with one query to the database.
SELECT * FROM Students t JOIN (SELECT CEIL(MAX(ID)*RAND()) AS ID FROM Students) AS x ON t.ID >= x.ID LIMIT 1
With the above query, I have selected a random student, with that I can go in and check if they have three subjects with SELECT count(subjects) FROM Students WHERE id=random_id.
If the count returned is below three, then I throw away the results and run the first query again.
How would I attempt this in one query?
This is tested and working:
SELECT *
FROM Students s
JOIN (
SELECT student_id
FROM Student_Grades
GROUP BY student_id
HAVING COUNT(*) >= 3
ORDER BY RAND()
LIMIT 1
) rs
ON rs.student_id = s.id
JOIN
Student_Grades sg
ON sg.student_id = s.id
Here's the SQL Fiddle: http://sqlfiddle.com/#!2/e5b5b/1

Filter fields from 1/n table using clause on multiple columns

ok, first of all sorry for the title, but I could not work out a better one :(
This is the problem:
I have two tables, properties and properties_rooms, linked each other by the propery ID.
properties table:
+---------------+------------+
| id_properties | pr_title |
+---------------+------------+
| 1 | test |
| 2 | dummy |
+---------------+------------+
properties_rooms table:
+---------------+-------------------+--------------+----------+
| id_prop_rooms | pro_id_properties | pro_id_rooms | pro_size |
+---------------+-------------------+--------------+----------+
| 1 | 1 | 4 | 5.00 |
| 2 | 1 | 18 | 17.00 |
| 3 | 2 | 6 | 12.00 |
| 4 | 2 | 24 | 11.00 |
| 5 | 1 | 4 | 10.00 |
| 6 | 1 | 6 | 10.00 |
| 7 | 1 | 6 | 12.00 |
+---------------+-------------------+--------------+----------+
I'm working on an advanced search, where users can search for a property that has more than a rooms of the same type (ie two bedrooms, 3 bathrooms and so on).
Sadly, I find myself stuck on this, since I can't "filter" the same dataset with multiple clause; if i have to filter only one there will be no problems, since I can use an HAVING clause.
I worked out this select:
SELECT id_properties, pro_id_rooms, COUNT(*) as total,
IF ((pro_id_rooms = 4 AND COUNT(*) >= 2) OR (pro_id_rooms = 6 AND COUNT(*) >= 2), 1, 0) as flag
FROM `properties`
INNER JOIN properties_rooms ON id_properties = pro_id_properties
WHERE id_properties IN (4,10)
GROUP BY id_properties, pro_id_rooms
ORDER BY id_properties
Inside the IN clause there are the properties that I know they have at least one of requested rooms. They came from a previous query since I have to work with GROUP BY and HAVING.
The IF part inside the select is built at run-time, since I get the information from the request.
This is the result:
+---------------+--------------+-------+------+
| id_properties | pro_id_rooms | total | flag |
+---------------+--------------+-------+------+
| 1 | 4 | 2 | 1 |
| 1 | 6 | 2 | 1 |
| 1 | 18 | 1 | 0 |
| 2 | 6 | 1 | 0 |
| 2 | 24 | 1 | 0 |
+---------------+--------------+-------+------+
I think it could work, I only need to add an HAVING flag > 0 and I'm done.
My question is, is there anything better?
Tables aren't very large: properties one could be something like 1k, rooms one about 10k.
I'm afraid that if the user puts too much rooms, the query would become an enormous IF statement...
SELECT id_properties, SUM(pro_id_rooms = 4) AS bedrooms, SUM(pro_id_rooms = 6) AS bathrooms
FROM `properties`
INNER JOIN properties_rooms ON id_properties = pro_id_properties
WHERE id_properties IN (4,10)
GROUP BY id_properties
HAVING bedrooms >= 3 AND bathrooms >= 2
Changes
SUM(pro_id_rooms = 4) AS bedrooms, SUM(pro_id_rooms = 6) AS bathrooms
For each checkbox the user has selected, you need a SUM(pro_id_rooms = x) AS nrofx in your WHERE.
HAVING bedrooms >= 3 AND bathrooms >= 2
This is where you check the number of a particular room.

Categories