SQLite foreach type of row - php

I have got table for example
+------+--------+--------+---------------------+
| Type | Value1 | Value2 | DateAdded |
+------+--------+--------+---------------------+
| 1 | a | a | 2014-03-31 20:00:00 |
| 2 | a | a | 2014-03-31 20:00:10 |
| 3 | a | a | 2014-03-31 20:00:25 |
| 1 | a | a | 2014-03-31 20:00:40 |
| 2 | a | a | 2014-03-31 20:00:50 |
| 3 | a | a | 2014-03-31 20:00:60 |
| 1 | a | a | 2014-03-31 20:01:10 |
| 2 | a | a | 2014-03-31 20:01:25 |
| 3 | a | a | 2014-03-31 20:01:35 |
+------+--------+--------+---------------------+
and many more rows... I want to to recieve in a single query:
20 rows WHERE type = 1 ORDER BY DateAdded DESC
20 rows WHERE type = 2 ORDER BY DateAdded DESC
20 rows WHERE type = 3 ORDER BY DateAdded DESC
and there can be more than three types.

One approach to this type of query is the count(*) in a subquery approach:
select *
from table t
where 20 >= (select count(*)
from table t2
where t2.type = t.type and
t2.DateAdded >= t.DateAdded
);
Count the number of rows with the same time that have a larger DateAdded and choose the ones that have up to 20 of them.

Related

PHP Codeigniter MySQL query - join 4 tables together, with 3 tables using group by one column from each table

Items Table
+----+------+
| id | name |
+----+------+
| 1 | abc |
| 2 | def |
| 3 | ghi |
+----+------+
Buy Table
+------+-------------+-------+---------+
| b_id | b_date | b_qty | b_itmid |
+------+-------------+-------+---------+
| 1 | 2020-05-01 | 10 | 1 |
| 2 | 2020-05-01 | 20 | 1 |
| 3 | 2020-05-02 | 5 | 2 |
| 3 | 2020-05-03 | 10 | 3 |
+------+-------------+-------+---------+
Rent Table
+------+-------------+-------+---------+
| r_id | r_date | r_qty | r_itmid |
+------+-------------+-------+---------+
| 1 | 2020-05-03 | 5 | 2 |
| 2 | 2020-05-03 | 10 | 2 |
| 3 | 2020-05-04 | 15 | 3 |
+------+-----------+---------+---------+
Sell Table
+------+-------------+-------+---------+
| s_id | s_date | s_qty | s_itmid |
+------+-------------+-------+---------+
| 1 | 2020-05-03 | 10 | 1 |
| 2 | 2020-05-05 | 20 | 3 |
| 3 | 2020-05-06 | 5 | 3 |
+------+-----------+---------+---------+
And I'm trying to get outputs with php foreach something like this ...
$trans_date
$buy_qty
$rent_qty
$sell_qty
$item
In case item id 1
+-------------+--------------+---------------+---------------+------+
| trans_date | buy_qty | rent_qty | sell_qty | item |
+-------------+--------------+---------------+---------------+------+
| 2020-05-01 | 30 | 0 | 0 | abc |
| 2020-05-02 | 0 | 0 | 0 | abc |
| 2020-05-03 | 0 | 0 | 10 | abc |
| 2020-05-04 | 0 | 0 | 0 | abc |
| 2020-05-05 | 0 | 0 | 0 | abc |
| 2020-05-06 | 0 | 0 | 0 | abc |
+-------------+--------------+---------------+---------------+------+
This is the query I've come for one table (b_date column has timestamp value)...
$query = $this->db->query("
SELECT FROM_UNIXTIME(b_date,'%d %M') AS date_b
, SUM(b_qty) AS qty_b
FROM buytable
WHERE b_itmid = 1
AND MONTH(FROM_UNIXTIME(b_date)) = MONTH(CURDATE())
GROUP
BY DATE(FROM_UNIXTIME(b_date))
");
if ($query->num_rows() > 0) {
foreach ($query->result() as $data) {
$result[] = $data;
}
return $result;
}
Finally I've found the correct answer https://stackoverflow.com/a/61875506/7554875
select d.date, b.qty_buy, r.qty_rent, s.qty_sell, i.name
from items i
cross join (
select b_date as date from buy
union all select r_date as date from rent
union all select s_date as date from sell
) d
left join (select b_date as date, b_itmid, sum(b_qty) qty_buy
from buy group by date, b_itmid) b
on b.date = d.date and b.b_itmid = i.id
left join (select r_date as date, r_itmid, sum(r_qty) qty_rent
from rent group by date, r_itmid) r
on r.date = d.date and r.r_itmid = i.id
left join (select s_date as date, s_itmid, sum(s_qty) qty_sell
from sell group by date, s_itmid) s
on s.date = d.date and s.b_itmid = i.id
where i.id = 1 and d.date >= date_format(curent_date, '%Y-%m-01')
order by d.date

MySql query in same column for different date

Please consider: I am talking about MySQL Database
I have two tables like this:
tbl_stock_info
+-----+--------+
| sId | sName |
+-----+--------+
| 1 | Apple |
| 2 | Google |
| 3 | Yahoo |
+-----+--------+
tbl_stock_data
+------------+----------+-------------+
| date | stock_id | stock_price |
+------------+----------+-------------+
| 2017-01-25 | 1 | 44.7 |
| 2017-01-25 | 3 | 51 |
| 2017-01-25 | 2 | 71.5 |
| 2017-01-24 | 1 | 44.9 |
| 2017-01-24 | 3 | 51.2 |
| 2017-01-24 | 2 | 71.3 |
+------------+----------+-------------+
The Output I am looking for is like this:
+-----+--------+----------+----------+
| sId | sName | Price_25 | Price_24 |
+-----+--------+----------+----------+
| 1 | Apple | 44.7 | 44.9 |
| 2 | Google | 71.5 | 71.3 |
| 3 | Yahoo | 51 | 51.2 |
+-----+--------+----------+----------+
Any assistance would be greatly appreciated.
You can do it with a query like this. it search the newest 2 dates in the table and generate your query, but the column name are fix. if you want also to change them you must use a prepared statement.
SELECT
si.*
,SUM(if(sd1.`date` = ( SELECT DISTINCT `date` FROM tbl_stock_data ORDER BY `date` DESC LIMIT 0,1), sd1.stock_price ,0) ) as lastday
,SUM(if(sd1.`date` = ( SELECT DISTINCT `date` FROM tbl_stock_data ORDER BY `date` DESC LIMIT 1,1), sd1.stock_price ,0) ) as daybefore
FROM tbl_stock_info si
LEFT JOIN tbl_stock_data sd1 ON sd1.stockid = si.sId
GROUP BY si.sId;
sample
MariaDB [l]> SELECT * FROM tbl_stock_info;
+-----+--------+
| sId | sNAme |
+-----+--------+
| 1 | Apple |
| 2 | Google |
| 3 | Yahoo |
+-----+--------+
3 rows in set (0.00 sec)
MariaDB [l]> SELECT * FROM tbl_stock_data;
+----+------------+---------+-------------+
| id | date | stockid | stock_price |
+----+------------+---------+-------------+
| 1 | 2017-01-25 | 1 | 44.70 |
| 2 | 2017-01-25 | 3 | 51.00 |
| 3 | 2017-01-25 | 2 | 71.50 |
| 4 | 2017-01-24 | 1 | 44.90 |
| 5 | 2017-01-24 | 3 | 51.20 |
| 6 | 2017-01-24 | 2 | 71.30 |
| 7 | 2017-01-23 | 1 | 99.00 |
| 8 | 2017-01-22 | 2 | 22.00 |
| 9 | 2017-01-20 | 3 | 33.13 |
+----+------------+---------+-------------+
9 rows in set (0.01 sec)
test
MariaDB [l]> SELECT
-> si.*
-> ,SUM(if(sd1.`date` = ( SELECT DISTINCT `date` FROM tbl_stock_data ORDER BY `date` DESC LIMIT 0,1), sd1.stock_price ,0) ) as lastday
-> ,SUM(if(sd1.`date` = ( SELECT DISTINCT `date` FROM tbl_stock_data ORDER BY `date` DESC LIMIT 1,1), sd1.stock_price ,0) ) as daybefore
-> FROM tbl_stock_info si
-> LEFT JOIN tbl_stock_data sd1 ON sd1.stockid = si.sId
-> GROUP BY si.sId;
+-----+--------+---------+-----------+
| sId | sNAme | lastday | daybefore |
+-----+--------+---------+-----------+
| 1 | Apple | 44.70 | 44.90 |
| 2 | Google | 71.50 | 71.30 |
| 3 | Yahoo | 51.00 | 51.20 |
+-----+--------+---------+-----------+
3 rows in set (0.00 sec)
MariaDB [l]>

Symfony - Subquery in doctrine2

I have a set of posts on monthly basis. i need an array which contains total records of posts posted in each month (including zeros).
I fail to write it in dql :( Any ideas plz ?
Sample Data:
+----+---------------------+
| id | date |
+----+---------------------+
| 24 | 2012-12-16 16:29:56 |
| 1 | 2013-02-25 14:57:09 |
| 2 | 2013-02-25 14:59:37 |
| 4 | 2013-02-25 15:12:44 |
| 5 | 2013-02-25 15:14:18 |
| 7 | 2013-02-26 11:31:31 |
| 8 | 2013-02-26 11:31:59 |
| 10 | 2013-02-26 11:34:47 |
| 14 | 2013-03-04 04:39:02 |
| 15 | 2013-03-04 05:44:44 |
| 16 | 2013-03-04 05:48:29 |
| 19 | 2013-03-07 15:22:34 |
| 20 | 2013-03-15 12:24:43 |
| 21 | 2013-03-16 16:27:43 |
| 22 | 2013-03-16 16:29:28 |
| 23 | 2013-03-16 16:29:56 |
| 11 | 2013-03-17 11:35:12 |
+----+---------------------+
SQL query:
SELECT count(b.id) as totalRec
FROM (
SELECT 'January' mnth
UNION ALL
SELECT 'February' mnth
UNION ALL
SELECT 'March' mnth
) a
LEFT JOIN post b
ON a.mnth = DATE_FORMAT(b.date, '%M') AND
year(b.date) = '2013' AND
DATE_FORMAT(b.date, '%M') IN ('January', 'February', 'March')
GROUP BY year(b.date)-month(b.date)
ORDER BY b.date ASC
OUTPUT
+----------+
| totalRec |
+----------+
| 0 |
| 7 |
| 9 |
+----------+
Count all posts grouped by month, and filter out the months you want:
SELECT count(*) as totalRec, DATE_FORMAT(b.date, '%m%Y') as month
FROM post b
WHERE month IN('012013', '022013', '032013')
GROUP BY month
ORDER BY b.date ASC
Will result in:
+----------+----------+
| totalRec | month |
+----------+----------+
| 0 | 012013 |
| 7 | 022013 |
| 9 | 032013 |
+----------+----------+

Find the number of rooms availble from the below table structure

I have the following table structure:
roominfo table
+---------+----------------+---------------+
| Room_id | room_type_name | maximum_rooms |
+---------+----------------+---------------+
| 1 | A | 16 |
| 2 | B | 14 |
| 3 | C | 7 |
| 4 | D | 2 |
| 5 | E | 2 |
+---------+----------------+---------------+
bookedtable stores all the rooms booked within that date:
+------------+--------------+---------------+----------------+---------+
| room_bk_id | checkin_date | checkout_date | maxroomsbooked | room_id |
+------------+--------------+---------------+----------------+---------+
| 1 | 2014-01-28 | 2014-01-29 | 8 | 1 |
| 2 | 2014-01-29 | 2014-01-30 | 2 | 4 |
| 3 | 2014-01-28 | 2014-01-29 | 4 | 1 |
+------------+--------------+---------------+----------------+---------+
bookingprogress table to avoid the race condition (it blocks upto the expire time) I set the maximum expire time as 15 minutes from current time
+------------+----------------+-----------------+----------------+---------+---------------+---------------------+
| room_pg_id | checkinpg_date | checkoutpg_date | maxroomsbooked | room_id | sessionid | ExpireTime |
+------------+----------------+-----------------+----------------+---------+---------------+---------------------+
| 1 | 2014-01-28 | 2014-01-29 | 2 | 1 | AdsddsA23asd | 2014-01-28 00:15:00 |
| 2 | 2014-01-29 | 2014-01-30 | 2 | 5 | AdsQWerasdwe | 2014-01-28 00:18:00 |
| 3 | 2014-01-28 | 2014-01-29 | 1 | 2 | BdrtQWerasdwe | 2014-01-28 00:20:00 |
+------------+----------------+-----------------+----------------+---------+---------------+---------------------+
The workflow is:
User checks for the available rooms by providing checkin date, checkout date and no of rooms.
I need to find and display the rooms are available which are not blocked or booked for that particular period.
The executed query was (might be small mistakes -- Here I gave overview of what I have done --So modified my query according to that)
SELECT tbook.*,
SUM(tbook.maxroomsbooked + tprogress.maxroomsbooked) AS bookedrooms
FROM bookedtable AS tbook
JOIN bookingprogress AS tprogress USING (Room_id)
JOIN roominfo AS troomtype USING (Room_id)
WHERE tbook.checkout_date > '2014-01-28'
AND tprogress.checkoutpg_date > '2014-01-28'
AND tprogress.ExpireTime < '2014-01-27 00:10:00'
AND tprogress.room_id = 1
GROUP BY Room_id
From the above tables I tried to get the rooms which are available for booking. But I didn't get the expected result.
See it on sqlfiddle.
Could you please provide me with the solution?
One way would be to use NOT EXISTS subqueries. For example, if a user is interested in booking '2014-02-01' to '2014-02-07':
SELECT *
FROM roominfo r
WHERE NOT EXISTS (
SELECT *
FROM bookedtable b
WHERE b.room_id = r.room_id
AND NOT (
b.checkin_date < '2014-02-07'
AND b.checkout_date > '2014-02-01'
)
LIMIT 1
)
AND NOT EXISTS (
SELECT *
FROM bookingprogress p
WHERE p.room_id = r.room_id
AND p.ExpireTime > CURRENT_TIME
AND NOT (
p.checkinpg_date < '2014-02-07'
AND p.checkoutpg_date > '2014-02-01'
)
LIMIT 1
)

SQL request for several tables and operations in MySQL

I have the following 3 tables: unit, stage, stats.
unit stage
+----+--------+ +----+-------+---------------------+
| id | status | | id |unit_id| date |
+----+--------+ +----+-------+---------------------+
| 1 | 2 | | 1 | 2 | 2013-11-22 00:00:00 |
| 2 | 3 | | 2 | 2 | 2013-11-26 12:00:00 |
| 3 | 3 | | 3 | 3 | 2013-10-11 00:00:00 |
| 4 | 0 | | 4 | 1 | 2013-12-29 00:00:00 |
+----+--------+ +----+-------+---------------------+
stats
+----+----------+---------------------+-------+
| id | stage_id | date | clicks|
+----+----------+---------------------+-------+
| 1 | 1 | 2013-11-22 00:00:00 | 10 |
| 2 | 1 | 2013-11-23 00:00:00 | 20 |
| 3 | 1 | 2013-11-24 00:00:00 | 25 |
| 4 | 2 | 2013-11-26 00:00:00 | 15 |
| 5 | 2 | 2013-11-27 12:00:00 | 21 |
| 6 | 3 | 2013-12-29 00:00:00 | 8 |
+----+----------+---------------------+-------+
I need a request, that will produce the following response:
+---------+---------------------+-----------------------+
| unit.id | stage.min.date | sum(stats.max.clicks) |
+---------+---------------------+-----------------------+
| 2 | 2013-11-22 00:00:00 | 46 |
| 3 | 2013-12-29 00:00:00 | 8 |
+---------+---------------------+-----------------------+
by the following rules:
1) unit.id - show only units with unit.status=3
2) stage.min.date - minimal stage.date for corresponding unit_id
3) sum(stats.max.clicks) - sum of stats.clicks with max dvalues for each stage_id associated with corresponding unit_id. In my example 46 = 25(stage_id=1) + 21(stage_id=2)
The problem is in min.date and sum of clicks - I have no idea how to get it in one query. Definitely it`s not a problem to do it using php code and several requests.
Schema in SQL Fiddle
Thanks in advance.
I just ask myself, why I do this? Your example resonse has an error, and does not match your fiddle... but:
SELECT
cc.unit_id, MIN(cc.date) as stage_min_date , SUM(dd.clicks) as stats_max_clicks
FROM
stage cc
LEFT JOIN (
SELECT
bb.stage_id, bb.clicks
FROM
stats bb LEFT JOIN (
SELECT id, stage_id, MAX(date) AS max_date
FROM stats
GROUP BY stage_id
) aa
ON
aa.max_date = bb.date
WHERE
aa.max_date IS NOT NULL
) dd
ON cc.id = dd.stage_id
LEFT JOIN unit ee
ON ee.id = cc.unit_id
WHERE ee.status = 3
GROUP BY cc.unit_id
...

Categories