I want to generate daywise report from two table
Table 1: opd
CREATE TABLE `opd` (
`id` int(50) NOT NULL,
`Date` date NOT NULL,
`time` time NOT NULL,
`opd_no` varchar(150) NOT NULL,
`patientid` varchar(150) DEFAULT NULL,
`name` varchar(150) NOT NULL,
);
Table structure
id
Date
Time
opd_no
Patient_id
name
1
2022-03-02
18:30:10
OPD/2122/1
PT01
Siba
2
2022-03-03
18:30:10
OPD/2122/2
PT02
Deba
3
2022-03-04
18:30:10
OPD/2122/3
PT03
Haris
4
2022-03-04
18:31:10
OPD/2122/4
PT04
ravish
Table 2: ipd_pn
CREATE TABLE `ipd_pn` (
`id` int(11) NOT NULL,
`ipd_no` varchar(40) DEFAULT NULL,
`patientid` varchar(170) NOT NULL,
`opd_reg_date` date DEFAULT NULL,
`time` time DEFAULT NULL,
`opd` varchar(40) DEFAULT NULL,
`date` date DEFAULT NULL,
)
Table structure
id
IPD_no
Patient_id
opd_Reg_date
time
opd_no
date
1
IPD/2122/1
PT01
2022-03-02
15:40:10
OPD/2122/1
2022-03-02
2
IPD/2122/2
PT03
2022-03-04
16:35:10
OPD/2122/3
2022-03-03
3
IPD/2122/3
PT02
2022-03-03
15:45:10
OPD/2122/2
2022-03-03
T tried to generate daywise how much opdno's generated by the below query
SELECT DATE(Date) AS date, COUNT(opdno) AS total_opd
FROM opd
WHERE (date BETWEEN '2022-02-1' AND '2022-03-28')
GROUP BY Date
Got output like below
date
total_opd
2022-03-02
1
2022-03-03
1
2022-03-04
2
But I can't generate how much ipd no's generated in this date period.
Please help.
I want a report like below
date
total_opd
total_ipd
2022-03-02
1
1
2022-03-03
1
1
2022-03-04
2
1
I tried with join query i.e
SELECT DATE(Date) AS date, COUNT(opdno) AS total_opd
FROM opd 0
INNER JOIN ipd_pn i ON o.Date = i.date
WHERE (date BETWEEN '2022-02-1' AND '2022-02-28')
GROUP BY Date
But that gives date ambiguity error.
So please try to help me how can I generate reports from both the tables.
You can try to use UNION ALL to combine two tables in a subquery then use a flag column to represent which row from opd or ipd_pn
SELECT date,
SUM(flag = 1) total_opd,
SUM(flag = 2) total_ipd
FROM (
SELECT DATE(Date) AS date, 1 flag
FROM opd
UNION ALL
SELECT Reg_date,2
FROM ipd_pn
) t1
WHERE date between '2022-02-1' and '2022-03-28'
GROUP BY Date
sqlfiddle
Related
i want to sum all the values in a specific date in mysql but idk what is the right syntax
CREATE TABLE `trans` (
`id` int(12) NOT NULL,
`date_sold` datetime NOT NULL,
`total` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `trans`
ADD PRIMARY KEY (`id`);
ALTER TABLE `trans`
MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
id
date_sold
total
1
2021-02-23
12
2
2021-02-23
6
3
2021-02-24
32
4
2021-02-24
10
now i want to sum all the values in that specific date
ex:
id
date
total
1
2021-02-23
18
2
2021-02-24
42
is that possible?
Alternative Use of ROW_NUMBER() function. Because ROW_NUMBER() isn't supported in below v5.8. First calculate date wise total and then apply id incrementally.
-- MySQL(5.6)
SELECT (#row_number:= #row_number + 1) id
, t.date_sold, t.total
FROM (SELECT date_sold
, SUM(total) total
FROM trans
GROUP BY date_sold ) t, (SELECT #row_number := 0) x
ORDER BY t.date_sold
Please check from URL https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=5cc2305b465ac2454be5bdb1a9e8af4a
I am working with agricultural product management system. I have a question regarding a MySQL query. I would like to know how to create the same query using Laravel query builder:
SELECT
vegitables.name, vegitables.image, vegitables.catagory,
AVG(price_wholesale),
SUM(CASE WHEN rank = 1 THEN price_wholesale ELSE 0 END) today,
SUM(CASE WHEN rank = 2 THEN price_wholesale ELSE 0 END) yesterday
FROM (
SELECT
veg_id, price_wholesale, price_date,
RANK() OVER (PARTITION BY veg_id ORDER BY price_date DESC) as rank
FROM old_veg_prices
) p
INNER JOIN vegitables ON p.veg_id = vegitables.id
WHERE rank in (1,2)
GROUP BY veg_id
This Output result get when run query in database:
Following two table are used to get today price yesterday price and price average get from each product.
CREATE TABLE `vegitables` (
`id` bigint(20) UNSIGNED NOT NULL,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`image` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`catagory` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`total_area` int(11) NOT NULL COMMENT 'Total area of culativate in Sri Lanka (Ha)',
`total_producation` int(11) NOT NULL COMMENT 'Total production particular product(mt)',
`annual_crop_count` int(11) NOT NULL COMMENT 'how many time can crop pre year',
`short_dis` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `vegitables`
ADD PRIMARY KEY (`id`);
ALTER TABLE `vegitables`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
COMMIT;
CREATE TABLE `old_veg_prices` (
`id` bigint(20) UNSIGNED NOT NULL,
`veg_id` int(11) NOT NULL,
`price_wholesale` double(8,2) NOT NULL,
`price_retial` double(8,2) NOT NULL,
`price_location` int(11) NOT NULL,
`price_date` date NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `old_veg_prices`
ADD PRIMARY KEY (`id`);
ALTER TABLE `old_veg_prices`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
COMMIT;
I try this site to convert to MySQL query to query builder code. But it show some error's could find it out. Any Way i want to run this code in Laravel with any method??
Your query will not return the data for yesterday and today; it will return the data for two most recent dates (e.g. if today is 2021-11-01 and most recent two dates for for carrots are 2021-10-25 and 2021-10-20 it will use those two dates). Using RANK() ... IN (1, 2) is also incorrect because it can return ranks such as 1 followed by 3 instead of 2.
To get today and yesterday prices you don't need window functions. Just use appropriate where clause and conditional aggregation:
SELECT vegitables.name
, vegitables.image
, vegitables.catagory
, AVG(old_veg_prices.price_wholesale) AS avgwholesale
, SUM(CASE WHEN old_veg_prices.price_date = CURRENT_DATE - INTERVAL 1 DAY THEN old_veg_prices.price_wholesale END) AS yesterday
, SUM(CASE WHEN old_veg_prices.price_date = CURRENT_DATE THEN old_veg_prices.price_wholesale END) AS today
FROM vegitables
INNER JOIN old_veg_prices ON vegitables.id = old_veg_prices.veg_id
WHERE old_veg_prices.price_date IN (CURRENT_DATE - INTERVAL 1 DAY, CURRENT_DATE)
GROUP BY vegitables.id -- other columns from vegitables table are functionally dependent on primary key
The Laravel equivalent would be:
DB::table('vegitables')
->Join('old_veg_prices', 'old_veg_prices.veg_id', '=', 'vegitables.id')
->whereRaw('old_veg_prices.price_date IN (CURRENT_DATE - INTERVAL 1 DAY, CURRENT_DATE)')
->select(
'vegitables.name',
'vegitables.image',
'vegitables.catagory',
DB::raw('AVG(old_veg_prices.price_wholesale) AS avgwholesale'),
DB::raw('SUM(CASE WHEN old_veg_prices.price_date = CURRENT_DATE - INTERVAL 1 DAY THEN old_veg_prices.price_wholesale END) AS yesterday'),
DB::raw('SUM(CASE WHEN old_veg_prices.price_date = CURRENT_DATE THEN old_veg_prices.price_wholesale END) AS today')
)
->groupBy(
'vegitables.id',
'vegitables.name',
'vegitables.image',
'vegitables.catagory'
)
->get();
"Query builder" features of abstraction products often leave out some possible SQL constructs. I recommend you abandon the goal of reverse engineering SQL back to Laravel and simply perform the "raw" query.
Also...
rank() OVER (PARTITION BY veg_id ORDER BY price_date DESC) as rank
requires MySQL 8.0 (MariaDB 10.2).
And suggest you avoid the alias "rank" since that is identical to the name of a function.
I'm looking to count the number of records based on matching a datetime values:
create table `weather` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`dt_iso` datetime DEFAULT NULL,
`weather_main` varchar(60) DEFAULT NULL);
insert into `weather` (`dt_iso`,`weather_main`) values ("2019-01-01 23:00:00","cloud"), ("2019-01-02 00:00:00","sun"), ("2019-01-02 01:00:00","cloud");
create table `incidents` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`Incident_Date` datetime DEFAULT NULL);
insert into `incidents` (`Incident_Date`) values ("2019-01-01 23:50:00"), ("2019-01-01 23:50:00"), ("2019-01-09 10:05:00");
In SQL Fiddle: http://sqlfiddle.com/#!9/489f57
This is the type of output I am seeking:
dt_iso, weather_main, count(incidents),
2019-01-01T23:00:00, cloud, 0
2019-01-02T00:00:00, sun, 2
2019-01-02T01:00:00, cloud, 0
It looks like you're trying to count incidents in the hour prior to the time in the weather table, which you can do with this query:
SELECT w.dt_iso, w.weather_main, COALESCE(COUNT(i.id), 0) AS incidents
FROM weather w
LEFT JOIN incidents i ON i.Incident_Date > w.dt_iso - INTERVAL 1 HOUR
AND i.Incident_Date <= w.dt_iso
GROUP BY w.id
Output:
dt_iso weather_main incidents
2019-01-01T23:00:00Z cloud 0
2019-01-02T00:00:00Z sun 2
2019-01-02T01:00:00Z cloud 0
Demo on SQLFiddle
I have a table with orders data:
CREATE TABLE `orders` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL DEFAULT '0',
`price` decimal(6,3) unsigned NOT NULL,
`created` datetime DEFAULT NULL,
`paid` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
I need to get price sum of orders in 12 weeks periods, where first period starts on a week when the very first order was paid, and each next period starts one week later than previous (this to have possibility to compare data in 12 weeks periods). So eventually there must be periods like 1-12, 2-13, etc.
Important detail: I can't use variables in query, because this query will be used in BI Tool, where queries with variables behave unexpected.
Did it next way:
SELECT `periods`.*, SUM(`orders`.`price`) AS `revenue`
FROM (SELECT DISTINCT FROM_DAYS(TO_DAYS(`paid`) - MOD(TO_DAYS(`paid`) -1, 7)) AS `period_start`,
(FROM_DAYS(TO_DAYS(`paid`) - MOD(TO_DAYS(`paid`) -1, 7)) + INTERVAL 12 WEEK) AS `period_end`
FROM `orders`
) AS `periods`
LEFT JOIN `orders` ON DATE(`orders`.`paid`) BETWEEN `periods`.`period_start` AND `periods`.`period_end`
GROUP BY `periods`.`period_end`
Small explanation: at first I define 12 week periods in subquery, using same table data. By doing this
DISTINCT FROM_DAYS(TO_DAYS(`paid`) - MOD(TO_DAYS(`paid`) -1, 7))
I shift paid value to the beginning of week.
With this
(FROM_DAYS(TO_DAYS(`paid`) - MOD(TO_DAYS(`paid`) -1, 7)) + INTERVAL 12 WEEK)
I add 12 weeks to the date means beginning of week.
Eventually I get result like this:
| period_start | period_end |
| 2015-07-19 | 2015-10-11 |
| 2015-07-26 | 2015-10-18 |
Then I simply join orders table and group data by end of period.
Looks like it does what I need.
Hi I'm trying to convert my MySQL database to MSSQL one so what I'm doing is changing most of my queries. Then I encountered the GROUP BY problem in the MSSQL so I was stuck in this part.
tbl_assign role:
tar_id int IDENTITY(1,1) PRIMARY KEY,
tar_auth int NOT NULL,
tar_role varchar(255) NOT NULL,
tar_group int NOT NULL,
tar_division int NOT NULL,
tar_add varchar(255) NOT NULL,
tar_edit varchar(255) NOT NULL,
tar_view varchar(255) NOT NULL,
tar_delete varchar(255) NOT NULL,
tar_updated_date datetime NOT NULL,
tar_updated_by int NOT NULL,
tar_owner_id int NOT NULL,
tar_assign_date datetime NOT NULL,
tar_is_deleted tinyint NOT NULL
tbl_user:
u_id int NOT NULL,
u_uname varchar(255) NOT NULL,
u_pword varchar(255) NOT NULL,
u_fname varchar(255) NOT NULL,
u_mname varchar(255) NOT NULL,
u_lname varchar(255) NOT NULL,
u_spark_id varchar(255) NOT NULL,
u_email varchar(255) NOT NULL,
u_mobile decimal(11,0) NOT NULL,
u_address varchar(255) NOT NULL,
u_div int NOT NULL,
u_group int NOT NULL,
u_role int NOT NULL,
u_updated_by int NOT NULL,
u_updated_date datetime NOT NULL,
u_reg_date datetime NOT NULL,
is_active tinyint NOT NULL,
is_online tinyint NOT NULL,
u_photo varchar(MAX) NOT NULL
Sample data
tbl_user:
u_id - 20
u_uname - USERNAME
u_pword - *********
u_fname - Fname
u_mname - Mname
u_lname - Lname
u_spark_id - 1
u_email - email#sample.com
u_mobile - 0
u_address - Address
u_div - 0
u_group - 0
u_role - 0
u_updated_by - 1
u_updated_date - 2015-07-30 00:00:00
u_reg_date - 2015-04-08 00:00:00
is_active - 1
is_online - 1
u_photo - 0
tbl_assign_role:
tar_id - 264
tar_auth - 2
tar_role - 44
tar_group - 1
tar_division - 1
tar_add - 1-1-1-1-1-1-1-0-0-1-0-1-1-0-0
tar_edit - 1-1-1-1-1-1-1-0-0-1-0-1-1-0-0
tar_view - 1-1-1-1-1-1-1-0-0-1-0-1-1-0-0
tar_delete - 0-0-0-0-0-0-0-0-0-0-0-0-0-0-0
tar_updated_date - 2015-04-08 11:51:50.000
tar_updated_by - 17
tar_owner_id - 20
tar_assign_date - 2015-04-08 11:51:50.000
tar_is_deleted - 0
The tbl_assign_role has 9 more entries that has the same owner_id but different in the other columns.
MySQL query:
SELECT * FROM tbl_user
JOIN tbl_assign_role ON tbl_user.u_id = tbl_assign_role.tar_owner_id
WHERE is_active = 1
AND u_id !=1
AND tar_is_deleted = 0
GROUP BY tbl_assign_role.tar_owner_id
ORDER BY tbl_user.u_updated_date DESC
Result of MySQL query has only one row. It will give the first entry on the tbl_assign_role that has the same owner_id.
MSSQL query:
SELECT * FROM tbl_user
JOIN tbl_assign_role ON tbl_user.u_id = tbl_assign_role.tar_owner_id
WHERE is_active = 1
AND u_id !=1
AND tar_is_deleted = 0
ORDER BY tbl_user.u_updated_date DESC
Result of MSSQL query has ten rows. It will give all the result of the tbl_assign_role that has the same owner_id.
How can I achieve the same result in the MySQL query?
For many databases, and MS SQL Server is one, it is not possible to specify just a single column in the GROUP BY clause, but use the wildcard for all columns in the select clause. MySQL is the odd one here, it does allow this.
So, the message is simple. You MUST specify the non-aggregating columns in the GROUP BY clause. No exceptions.
You might want to consider use of ROW_NUMBER() OVER([partition by ...] order by ...) if you are really just wanting to return a single row per tar_owner_id.
SELECT
*
FROM (
SELECT
*
, ROW_NUMBER() OVER (PARTITION BY tbl_assign_role.tar_owner_id
ORDER BY tbl_user.u_updated_date DESC) AS rn
FROM tbl_user
JOIN tbl_assign_role
ON tbl_user.u_id = tbl_assign_role.tar_owner_id
WHERE is_active = 1
AND u_id != 1
AND tar_is_deleted = 0
) AS D
WHERE D.rn = 1
ORDER BY <<some column(s)>>
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY