I have original data like this.
Original Data
I need to create two report with it, this is the first report :
First Report
The running value can be achieved with this expression
RunningValue(Fields!City.Value+Fields!Month.Value,CountDistinct,"Region")
The second report i need is this:
Second Report
What can i do to add logic to the running value so it can avoid numbering row with Sum(Amount) zero ?
I'm not sure you can do this using RunningValue, other people may know of a way.
What I did was move the logic to the query.
I reproduced some data to match your final report numbers (your sample data does not match the sample report output).
Here's the sample data I used.
DECLARE #t TABLE(Region varchar(10), City varchar(10), MonthID int, Amount int)
INSERT INTO #t VALUES
('Asia', 'Tokyo', 4, 1000),
('Asia', 'Tokyo', 4, 500),
('Asia', 'Tokyo', 5, 2000),
('Asia', 'Tokyo', 5, -2000),
('Asia', 'Tokyo', 6, 1000),
('Asia', 'Tokyo', 6, -500),
('Asia', 'Bangkok', 4, 500),
('Asia', 'Bangkok', 4, 500),
('Asia', 'Bangkok', 5, 3000),
('Asia', 'Bangkok', 5, -500),
('Asia', 'Bangkok', 6, -750),
('Asia', 'Bangkok', 6, 750)
SELECT
*
, ROW_NUMBER() OVER(PARTITION BY Region, City ORDER BY MonthID) as RowN1
, ROW_NUMBER() OVER(PARTITION BY (CASE Amount WHEN 0 THEN 0 ELSE 1 END), Region, City ORDER BY MonthID) as RowN2
FROM
(
SELECT
Region, City, MonthID
, SUM(Amount) AS Amount
FROM #t
GROUP BY Region, City, MonthID
) x
ORDER BY Region, City DESC, MonthID
I used the ROW_NUMBER function to assign a row numbers for both reports.
The first one "RowN1" is a simple row number within city
The second one "RowN2" does the same thing but it partitions any zero values so they are not in the same partition as the other data.
This gives us the following dataset
Now you can use a simple table to display the result in your first report using RowN1
In your second report use RowN2 with the expression
=IIF(Fields!Amount.Value=0, Nothing, Fields!RowN2.Value)
This simply forces a blank to be displayed if the amount is zero.
I did this and got the following results.
Note: I used a month number in the data just to make sorting easier, in the report I used =MonthName(Fields!MonthID.Value) to show the actual name.
Related
I'm continuing a project from someone else where they stored the time in hh:mm/hh:mm format in the MySQL database with the delimiter /
How do I split up and compare between those hours with the TIME datatype?
Considering there are a finite and known number of fields, you could use this (admittedly) ugly solution to split the fields using SUBSTRING_INDEX and cast them to TIME for further comparison/manipulation.
SELECT
CAST(SUBSTRING_INDEX(monday,'/',1) AS TIME) AS 'monday_start',
CAST(SUBSTRING_INDEX(monday,'/',-1) AS TIME) AS 'monday_end',
CAST(SUBSTRING_INDEX(tuesday,'/',1) AS TIME) AS 'tuesday_start',
CAST(SUBSTRING_INDEX(tuesday,'/',-1) AS TIME) AS 'tuesday_end',
CAST(SUBSTRING_INDEX(wednesday,'/',1) AS TIME) AS 'wednesday_start',
CAST(SUBSTRING_INDEX(wednesday,'/',-1) AS TIME) AS 'wednesday_end',
CAST(SUBSTRING_INDEX(thursday,'/',1) AS TIME) AS 'thursday_start',
CAST(SUBSTRING_INDEX(thursday,'/',-1) AS TIME) AS 'thursday_end',
CAST(SUBSTRING_INDEX(friday,'/',1) AS TIME) AS 'friday_start',
CAST(SUBSTRING_INDEX(friday,'/',-1) AS TIME) AS 'friday_end',
CAST(SUBSTRING_INDEX(saturday,'/',1) AS TIME) AS 'saturday_start',
CAST(SUBSTRING_INDEX(saturday,'/',-1) AS TIME) AS 'saturday_end',
CAST(SUBSTRING_INDEX(sunday,'/',1) AS TIME) AS 'sunday_start',
CAST(SUBSTRING_INDEX(sunday,'/',-1) AS TIME) AS 'sunday_end'
FROM times
DB Fiddle
A tip of the cap to fellow Stack Overflow user madde74 for the inspiration in an older answer.
This will split and convert the thursday column's first time to data type TIME
SELECT TIME(SUBSTRING_INDEX(thursday,'/',1)) FROM YOUR_TABLE
Output
03:01:00
i hope you can finish the rest...
create database t
create table t (
user_id int,
dayofweek varchar(15),
timerange varchar(15)
)
insert into t (user_id, dayofweek, timerange) select 83, 'monday', '00:00/12:30'
<br>insert into t (user_id, dayofweek, timerange) select 83, 'tuesday', null
<br>insert into t (user_id, dayofweek, timerange) select 83, 'wednesday', '00:00/24:00'
<br>insert into t (user_id, dayofweek, timerange) select 83, 'thursday', '03:01/10:02'
<br>insert into t (user_id, dayofweek, timerange) select 83, 'friday', '00:00/24:00'
<br>insert into t (user_id, dayofweek, timerange) select 83, 'saturday', '00:00/24:00'
<br>insert into t (user_id, dayofweek, timerange) select 83, 'sunday', '00:00/24:00'
select *,
substring(timerange, 1, 2) as [timerange1hours],
substring(timerange, 4, 2) as [timerange1minutes],
substring(timerange, 7, 2) as [timerange2hours],
substring(timerange, 10, 2) as [timerange2minutes],
convert(int, substring(timerange, 7, 2)) - convert(int, substring(timerange, 1, 2)) as [diffhours],
convert(int, substring(timerange, 10, 2)) - convert(int, substring(timerange, 4, 2)) as [diffminutes]
from t
where timerange is not null
delete from t
On the basis of your explanation, I assume that two time elements on either side of '/' are to and from time. In other words monday column could be divided into to columns monday_from and monday_to and 00:00/12:30 could then be split with monday_from having 00:00 and monday_to having 12:30.
Following steps will help you achieve what you are after
You can split 00:00/12:30 using SUBSTRING_INDEX()
e.g. select SUBSTRING_INDEX('00:00/12:30', '/', 1) monday_to, SUBSTRING_INDEX('00:00/12:30', '/', -1) monday_from
You can then append :00 to each to represent seconds using CONCAT(). This will be insignificant as that data is not being recorded
Using str_to_date() function then you can convert this string into time
e.g. select str_to_date('12:30:00', %h:%i:%s)
- You can then compare these as time
select
str_to_date(CONCAT(SUBSTRING_INDEX('00:00/12:30', '/', 1), ':00'), %h:%i:%s) as monday_to,
str_to_date(CONCAT(SUBSTRING_INDEX('00:00/12:30', '/', -1), ':00'), %h:%i:%s) as monday_from
Note: I don't have MySQL DB handy so, SQL is not checked for syntactic error, may have small but correctable errors.
I have the following sample data:
id, user_id, action, date, item_id
(5, 1, 'created', '2016-09-08, 1),
(6, 1, 'sold', '2016-09-14, 1),
(7, 2, 'created', '2016-09-08, 2),
(8, 2, 'sold', '2016-09-30, 2),
(9, 3, 'created', '2016-10-08, 3)
I'm trying to create a Query that returns the percentage of items sold within 1 week. The value of the column: "action" represents if the item has been put up for sale, or sold. How could this look?. Should I do this by using a subquery or?
Expected result should be a single percentage (the number of items sold within 1 week, of the total number of items created).
Assuming that the data is indeed this simple, this can easily be done by joining the same table to itself. The first reference to the sample data can be aliased as created and will filter to items with an action of created. Likewise, the sold table reference will restrict itself to items with an action of sold.
Once that's done, we'll get a row of data that has an item's creation and sold dates. Anything that doesn't have a sold action is simply discarded by an inner join. The built in function datediff(date1, date2) will give us the number of days between our two dates. If this is less than or equal to 7, you know that it was sold within a week.
select
created.id
, created.user_id
, created.item_id
, datediff(created.date, sold.date) as days_to_sell
from
sample_data created
join sample_data sold
on created.item_id = sold.item_id
where
created.action = 'created'
and sold.action = 'sold'
and datediff(created.date, sold.date) <= 7
I have a MySQL table:
PriceRange (MinPrice DOUBLE, MaxPrice DOUBLE, TrdDate DATE)
I want to apply a multiplication factor on MinPrice and MaxPrice for all the records with TrdDate less than a particular date. For example,
Table before update:
(10, 12, 01-JAN-2016)
(12, 14, 02-JAN-2016)
(6, 7, 03-JAN-2016)
Table after update (with multiplication factor of 0.5 applied on all records for TrdDate < 03-JAN-2016):
(5, 6, 01-JAN-2016)
(6, 7, 02-JAN-2016)
(6, 7, 03-JAN-2016)
I know subquery will not work here as I can't update the same record that I am reading.
Can I solve above problem using JOIN or do I have to use cursor for it?
You can use a simple UPDATE query to solve this:
UPDATE PriceRange
SET MinPrice = MinPrice * 0.5, MaxPrice = MaxPrice * 0.5
WHERE TrdDate < '2016-01-03'
demo on dbfiddle.uk
I am developing a employee login system in which user check in and checkout timings are recorder. I have the following mySql table schema from which I would like to query the total working hours of an employee of a particular month.
AttendanceId UserId Operation CreatedDate
24 4 1 2016-03-20 23:18:59
25 4 2 2016-03-20 23:19:50
26 4 1 2016-03-20 23:20:28
27 4 2 2016-03-20 23:20:31
Operation 1 is for check in and operation 2 is for checkout. Can any one help me to build this query?
A pleasingly complicated question, thanks. My query deals with:
Attendances that aren't precisely measured in hours. The number of seconds is totalled and divided by 3600 at the end of the calculation.
Attendances that span the month boundary at either end (thanks strawberry)
Attendances in the current month that have started (there is an entry with operation "1") but not yet finished (there is no corresponding operation "2").
I used the following data for testing:
INSERT INTO Attendance(UserId, Operation, CreatedDate) VALUES
(4, 1, '2016-01-01 15:00:00'),
(4, 2, '2016-01-01 19:00:00'),
(4, 1, '2016-01-31 23:00:00'),
(4, 2, '2016-02-01 01:00:00'),
(4, 1, '2016-02-20 23:18:59'),
(4, 2, '2016-02-20 23:19:50'),
(4, 1, '2016-02-20 23:20:28'),
(4, 2, '2016-02-20 23:20:31'),
(4, 1, '2016-02-29 23:00:00'),
(4, 2, '2016-03-01 01:00:00'),
(4, 1, '2016-03-02 15:00:00'),
(4, 2, '2016-03-02 18:00:00'),
(4, 1, '2016-03-22 10:00:00');
The query selects all users' hours for a specific month. Selecting results for more than one month in one query is more complicated because of the possibility that attendances span month boundaries and if required it might be simplest to iterate over the months and run the query repeatedly, adjusting the four dates in the SQL appropriately.
The innermost query selects all arrival times and the corresponding departure time for all users. The outer query then restricts them to the current month, calculates the difference between the two times, and sums them by user.
SELECT UserId, SUM(TIMESTAMPDIFF(
SECOND,
GREATEST(TimeIn, '2016-02-01'),
LEAST(COALESCE(TimeOut, NOW()), '2016-03-01'))) / 3600 HoursInMonth
FROM (SELECT TimeIn.UserId, TimeIn.CreatedDate TimeIn, MIN(TimeOut.CreatedDate) TimeOut
FROM Attendance TimeIn
LEFT JOIN Attendance TimeOut ON TimeOut.UserId = TimeIn.UserId
AND TimeOut.Operation = 2
AND TimeOut.CreatedDate > TimeIn.CreatedDate
WHERE TimeIn.operation = 1
GROUP BY TimeIn.AttendanceId
ORDER BY TimeIn.CreatedDate) TimeInOut
WHERE DATE_FORMAT(TimeIn, '%Y-%m') = '2016-02'
OR DATE_FORMAT(TimeOut, '%Y-%m') = '2016-02'
OR (DATE_FORMAT(TimeIn, '%Y-%m') < '2016-02' AND TimeOut IS NULL)
GROUP BY UserId;
I have a mySql table call details. details table is having a column call date which is having date like 2015-02-01. There can be multiple rows from a same date.
I want to find how many rows COUNT() it contains for each month of the year.
for example,
'568', '192.168.1.100', '790', '1.00', '2014-11-14'
'569', '192.168.1.100', '780', '1.00', '2014-11-14'
'699', '192.168.1.100', '780', '1.00', '2014-11-16'
'767', '192.168.1.102', '780', '1.00', '2014-12-15'
'768', '192.168.1.102', '780', '1.00', '2014-12-15'
this should give COUNT like:
'2014-11-' as 3
'2014-12-' as 2
How can i do it using a sql select query.
Select DATE_FORMAT(My_Call_Date_Field, '%Y-%m') as MyYearAndMonth, Count(*) as MyCount
From My_Call_Details_Table Group By DATE_FORMAT(My_Call_Date_Field, '%Y-%m')
You can also use the CAST function of MySql.
Select substr(convert(My_Call_Date_Field, CHAR), 1, 7) as MyYearAndMonth, Count(*) From My_Call_Details_Table Group By substr(convert(My_Call_Date_Field, CHAR), 1, 7) Order By substr(convert(My_Call_Date_Field, CHAR), 1, 7)
In response to additional info specific to your case, as seen in your comment to the previous answer by Ed King: here it is :
SELECT DATE_FORMAT(detailtable.date, '%Y-%m') , AVG(detailtable.loadstate) as "load",count(detailtable.loadstate) as "count" from ruby_snmp.detailtable where ipaddtress='192.168.1.102' and date LIKE '2014-12-%' GROUP BY DATE_FORMAT(detailtable.date, '%Y-%m')
Convert to month and year using mysql functions, group and count:
SELECT month(calldate) as m, year(calldate) as y, count(*)
FROM calldetails
GROUP by m, y;
Given the additional information, I would do the following:
SELECT YEAR(detailtable.date) as y,
MONTH(detailtable.date) as m,
AVG(detailtable.loadstate) as "load",
count(detailtable.loadstate) as "count"
FROM ruby_snmp.detailtable
WHERE ipaddtress='192.168.1.102' and date LIKE '2014-12-%'
GROUP BY y, m;
The format variables y and m would be disregarded, but need to be there for the group to work. You can add the FORMAT function to give the specific YYYY-MM as was mentioned in the second post, or you can handle data presentation in the program / report writer.