Mysql : select aggregated values in between dates - mysql

I've got mysql query (generated by zf2), it looks like
SELECT `subt`.`from` AS `from`, SUM(ordered) AS `sum_ordered`,
SUM(income) AS `sum_income`, SUM(sales_by_payment) AS
`sum_sales_by_payment`
FROM (
SELECT `w`.`brand` AS `brand`, `w`.`article` AS `article`,
`w`.`subject` AS `subject`, `w`.`size` AS `size`, `w`.`from` AS
`from`, (
SELECT SUM(IFNULL(income,0)) AS `income`) AS `income`, (
SELECT SUM(IFNULL(income_sum_price,0)) AS `income_sum_price`) AS
`income_sum_price`, (
SELECT SUM(IFNULL(ordered,0)) AS `ordered`) AS `ordered`, (
SELECT SUM(IFNULL(ordered_sum_price,0)) AS `ordered_sum_price`) AS
`ordered_sum_price`, (
SELECT SUM(IFNULL(ordered_max_by_day,0)) AS `ordered_max_by_day`) AS
`ordered_max_by_day`, (
SELECT SUM(IFNULL(return_before_payment,0)) AS
`return_before_payment`) AS `return_before_payment`, (
SELECT SUM(IFNULL(return_before_payment_sum_price,0)) AS
`return_before_payment_sum_price`) AS
`return_before_payment_sum_price`, (
SELECT SUM(IFNULL(sales_by_payment,0)) AS `sales_by_payment`) AS
`sales_by_payment`, (
SELECT SUM(IFNULL(sales_by_payment_sum_price,0)) AS
`sales_by_payment_sum_price`) AS `sales_by_payment_sum_price`, (
SELECT SUM(IFNULL(`return`,0)) AS ```return```) AS `return`, (
SELECT SUM(IFNULL(`return_sum_price`,0)) AS ```return_sum_price```)
AS `return_sum_price`, (
SELECT SUM(IFNULL(`stock`,0)) AS ```stock```) AS `stock`, (
SELECT SUM(IF (sales_by_payment IS NOT NULL,
sales_by_payment_sum_price / sales_by_payment, NULL)) AS
`sale_price`) AS `sale_price`, (
SELECT SUM(income_sum_price * 0.62) AS `our_percent`) AS
`our_percent`, (
SELECT SUM(IFNULL(income_sum_price,0) * 0.25) AS
`cost_price_income`) AS `cost_price_select`, (
SELECT SUM(IFNULL(sales_by_payment_sum_price,0) -
(IFNULL(income_sum_price,0) * 0.25)) AS `profit`) AS `profit`, (
SELECT SUM(IF(income IS NOT NULL, (sales_by_payment / income) *
100, 0)) AS `sales_from_income`) AS `sales_from_income`, (
SELECT (SUM(sales_by_payment) / SUM(return_before_payment)) * 100 AS
`returns_buyout`) AS `returns_buyout`, (
SELECT SUM(return_before_payment) / SUM(ordered) * 100 AS `returns`) AS
`returns`, (
SELECT SUM(sales_by_payment) / SUM(ordered) * 100 AS `buyout`) AS
`buyout`, (
SELECT SUM(IFNULL(income,0) - IFNULL(sales_by_payment,0) +
IFNULL(`return`,0)) AS `total`) AS `total`, (
SELECT (SUM(IFNULL(income,0)) - SUM(IFNULL(stock,0)) -
SUM(IFNULL(`sales_by_payment`,0)) + SUM(IFNULL(`return`,0))) AS
`in_the_way`) AS `in_the_way`
FROM `wildberries` AS `w`
WHERE `from` >= '2016-02-01' AND `end` <= '2017-05-04'
GROUP BY `article`
ORDER BY `article` DESC
LIMIT 20 OFFSET 0) AS `subt`
GROUP BY DAY(`from`)
ORDER BY `from` ASC
If dates range are between one year, all works fine. But if i use different years, it returns only one row.
Could anyone give me advice - why is it happen and how should i modify query?
Table scheme is
CREATE TABLE `wildberries` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`brand` VARCHAR(50) NULL DEFAULT NULL,
`subject` VARCHAR(50) NULL DEFAULT NULL,
`article` VARCHAR(50) NULL DEFAULT NULL,
`size` VARCHAR(50) NULL DEFAULT NULL,
`income` VARCHAR(50) NULL DEFAULT NULL,
`income_sum_price` VARCHAR(50) NULL DEFAULT NULL,
`ordered` VARCHAR(50) NULL DEFAULT NULL,
`ordered_sum_price` VARCHAR(50) NULL DEFAULT NULL,
`ordered_max_by_day` VARCHAR(50) NULL DEFAULT NULL,
`return_before_payment` VARCHAR(50) NULL DEFAULT NULL,
`return_before_payment_sum_price` VARCHAR(50) NULL DEFAULT NULL,
`sales_by_payment` VARCHAR(50) NULL DEFAULT NULL,
`sales_by_payment_sum_price` VARCHAR(50) NULL DEFAULT NULL,
`return` VARCHAR(50) NULL DEFAULT NULL,
`return_sum_price` VARCHAR(50) NULL DEFAULT NULL,
`stock` VARCHAR(50) NULL DEFAULT NULL,
`source_file` VARCHAR(50) NULL DEFAULT NULL,
`from` DATE NULL DEFAULT NULL,
`end` DATE NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `article` (`article`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

In your subquery you group by column article, but you select column from. You don't tell the DBMS which of the article's froms you want to see. This is invalid according to the SQL standard, but MySQL lets this slip and gives you one of the article's froms arbitrarily chosen.
So for the first 20 articles you select rather random dates.
In your main query you group by these dates' days parts. This can result in 1 to 20 rows and is based on coincidence (i.e. how the records happen to be stored on disk at that moment and how the DBMS retrieves them).

Related

mysql order rows by a record with two different values

i have records that have value equal to 1 or 2 i want to order rows by this record like this
1
2
1
2
1
2
1
how can i do this order by only orders by DESC or ASC ?
note : there is a primary key id, and there is a created date
CREATE TABLE `users` (
`uid` INT(11) NOT NULL AUTO_INCREMENT,
`phone_number` VARCHAR(16) NOT NULL,
`password` VARCHAR(100) NOT NULL,
`first_name` VARCHAR(100) NOT NULL,
`last_name` VARCHAR(100) NOT NULL,
`sex` TINYINT(4) NOT NULL, << this will have only 1 or 2
`created_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`account_status` TINYINT(1) NOT NULL,
PRIMARY KEY (`uid`)
);
Try this query:
SELECT t.*
FROM (
SELECT STRAIGHT_JOIN uid, first_name ,
#y:=IF(#sex=sex,#y+1,1) AS rnk, #sex:=sex AS sex
FROM (SELECT #sex:=NULL) AS x
JOIN users
ORDER BY sex, uid DESC
) AS t
ORDER BY rnk ASC, sex ASC;

MYSQL QUERY : Select 1 rows photo from table for each album

I have a table with records and it has a table called gallery. I have inserted too many photo and I want to select only 2 random photo from each gallery.
here my structured
CREATE TABLE IF NOT EXISTS `gallery` (
`gallery_id` int(11) NOT NULL,
`gallery_name` varchar(100) NOT NULL,
`gallery_name_seo` varchar(120) NOT NULL,
`gallery_client` varchar(100) NOT NULL,
`gallery_date` date NOT NULL,
`gallery_type` int(2) NOT NULL,
`gallery_desc` text,
`gallery_publish` char(1) NOT NULL DEFAULT 'N' COMMENT 'Y = Yes & N = No',
`gallery_added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`deleted` int(11) NOT NULL DEFAULT '0'
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
and here another table
CREATE TABLE IF NOT EXISTS `gallery_photo` (
`id` int(10) NOT NULL,
`id_gallery` int(10) NOT NULL,
`file_name` varchar(255) NOT NULL,
`file_added` date NOT NULL,
`deleted` smallint(6) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=latin1;
acctually there many example here but i hard to understand,
how to create query from my problem.?
thanks
The following query would give you 1 random photo per id_gallery:
SELECT *
FROM (SELECT * FROM `gallery_photo` ORDER BY RAND()) as `rand_photos`
GROUP BY rand_photos.id_gallery
You could UNION it with itself to get 2 random photos for each gallery:
SELECT *
FROM (SELECT * FROM `gallery_photo` ORDER BY RAND()) as `rand_photo1`
GROUP BY rand_photo1.id_gallery
UNION
SELECT *
FROM (SELECT * FROM `gallery_photo` ORDER BY RAND()) as `rand_photo2`
GROUP BY rand_photo2.id_gallery
ORDER BY id_gallery

MySQL Order by subquery column

I have problem with sql query. The idea is to select all loans that are after payment (status 1/2/3) between 8 and 21 days with calculated value from payment_day til now.
I have already done some query but can't use columns days_after_payment and days_after_part_payment in WHERE section. I would like to have one column like days_after_payment based on loan type.
SELECT l.*,
(SELECT SUM(`value`) FROM `loan_part` WHERE `loan_id` = l.id AND `paid`=0) AS left_to_pay,
-(DATEDIFF((SELECT date FROM `loan_part` WHERE `loan_id` = l.id AND `paid`=0 AND `date`<CURDATE() ORDER BY `date` LIMIT 1), NOW())) AS days_after_part_payment,
-(DATEDIFF(l.payment_date, NOW())) AS days_after_payment
FROM loan l
WHERE (l.type=1 or l.type=2) AND (l.status=1 OR l.status=2 OR l.status=3)
GROUP BY l.client_id
ORDER BY
CASE l.type
WHEN 1 THEN days_after_payment
WHEN 2 THEN days_after_part_payment
ELSE 1 END
ASC
CREATE TABLE IF NOT EXISTS `loan` (
`id` int(11) NOT NULL,
`value` int(11) NOT NULL,
`client_id` int(11) NOT NULL,
`status` int(11) NOT NULL,
`type` int(11) NOT NULL,
`payment_date` date DEFAULT NULL
) ENGINE=MyISAM AUTO_INCREMENT=2068 DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `loan_part` (
`id` int(10) unsigned NOT NULL,
`loan_id` int(11) NOT NULL,
`value` float NOT NULL,
`date` date DEFAULT NULL,
`paid` tinyint(1) NOT NULL DEFAULT '0'
) ENGINE=MyISAM AUTO_INCREMENT=1751 DEFAULT CHARSET=utf8;
Update1 : I had to cut unnecessary columns and rewrite it into English from my native language.
ORDER BY 7
"7" means the 7th field in the SELECT. That works for GROUP BY also. I had to see the table definition to count how many in l.*.
How come id is not declared AUTO_INCREMENT?

MySQL Need advice on Query

I want to fetch latest 3 news from each news type.
CREATE TABLE IF NOT EXISTS `news` (
`news_id` int(8) NOT NULL AUTO_INCREMENT,
`news_heading` tinytext NOT NULL,
`news_description` text NOT NULL,
`news_date` date DEFAULT NOT NULL,
`news_type` tinyint(1) NOT NULL COMMENT '0- PEP|1 - MEDIA|2 - CONSULTING',
`created_date` datetime NOT NULL,
`modified_date` datetime NULL,
`display` tinyint(1) NOT NULL COMMENT '0- ON | 1 -OFF',
PRIMARY KEY (`news_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
Below Query will give me only 1 latest news from all type. Suggest me how we can achieve for top 3 from each type
SELECT * FROM (
SELECT * FROM `news`
ORDER BY `created_date` DESC
) AS TBL
GROUP BY `news_type`
Try this:
SELECT news_id, news_heading, news_description, news_date,
news_type, created_date, modified_date, display
FROM (SELECT news_id, news_heading, news_description, news_date,
news_type, created_date, modified_date, display,
IF(#news_type = #news_type:=news_type, #id:=#id+1, #id:=1) AS id
FROM news, (SELECT #id:=1, #news_type:=0) A
ORDER BY news_type, created_date DESC
) AS A
WHERE id <= 3;

View help. Pulling data from 3 tables

Okay, I need some major help with this subject. This is what I need the view to do. It needs to take Sum of the DKP_Change Column in the Attendance table
SELECT SUM(a.DKP_Change) FROM Attendance AS a GROUP BY Name
add the value of the initial DKP from the characters table
SELECT b.Inital_DKP FROM Characters AS b GROUP BY Name
Subtract the sum of the raid drops tabe cost
SELECT SUM(c.Cost) FROM Raid_Drops AS c GROUP BY Name
I'm entirely new to the idea of VIEWS and i'm not sure where to begin with, the name of the view should be DKP, the columns should be Name and Total_DKP, where total dkp is calculated from teh above select statements.
Here are the creates for all 3 tables.
CREATE TABLE `Attendance` (
`Date` date NOT NULL,
`Name` varchar(20) NOT NULL,
`Hours` int(11) NOT NULL,
`Penalty` float NOT NULL,
`Rank` set('Raider','Core','Elite') NOT NULL,
`Rate` int(11) NOT NULL,
`DKP_Change` float NOT NULL,
`RecordNumber` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`RecordNumber`)
) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=latin1
CREATE TABLE `Characters` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(25) NOT NULL,
`Class` varchar(25) NOT NULL,
`Spec` varchar(25) NOT NULL,
`Position` set('Healer','Tank','DPS') NOT NULL COMMENT 'Healer, Tank, or DPS',
`Usable` set('Cloth','Mail','Plate') NOT NULL COMMENT 'Type of Usable Armor? Cloth, Mail, Or Plate',
`Primary Stat` set('Agility','Strength','Intellect','Healer','Tank') NOT NULL COMMENT 'Used for Sorting Only(ie dps trinket with agility strength dps not eligible)',
`Initial_DKP` int(11) NOT NULL COMMENT 'DKP given at the start of current tier.',
`Total_DKP` int(11) NOT NULL COMMENT 'Huge Complicated Mess.',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
CREATE TABLE `Raid_Drops` (
`Record Number` int(11) NOT NULL,
`Date` date NOT NULL,
`Name of Item` varchar(25) NOT NULL,
`Item Slot` enum('Main Hand','Off Hand','Head','Neck','Shoulder','Back','Chest','Wrist','Hands','Waist','Legs','Feet','Ring 1','Ring 2','Trinket 1','Trinket 2') NOT NULL,
`Player_Name` varchar(25) NOT NULL,
`Cost` float NOT NULL,
PRIMARY KEY (`Record Number`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
You could
Join the three tables in a subselect, grouping on Name
Perform your calculations on the results of each subselect
The only part that's not entirely clear to me is if the names in Characters are unique or not. If they are, you can drop the group by. If they are not, the AVG might give you unexpected results.
SQL Statement
SELECT sumA
, initialB
, sumC
, sumA + initialB - sumC
, a.Name
FROM (
SELECT Name, SUM(DKP_Change) AS sumA
FROM Attendance
GROUP BY Name
) AS a
INNER JOIN (
SELECT Name, Inital_DKP AS initialB
FROM Characters
) AS b ON a.Name = b.Name
INNER JOIN (
SELECT Name, SUM(Cost) AS sumC
FROM Raid_Drops
GROUP BY Name
) AS c ON c.Name = b.Name