Merging two queries to get a single result in MySQL - mysql

I have the following two codes, I need to get the percentage by dividing the 'for_2018_19' by the 'total'. I don't know how to merge them and get a single result which is the percentage.
select sum(maternities) as total from merged
where City = 'Jeza' and Group = 'Unknown';
select sum(Maternities) as for_2018_19 from merged
where Year = '2016/17') percentage ;

You use bth query as the only give back single data, as subqueries
But yu should keep in mind that group is a reserved word, and you should avoid it
SELECT
(select sum(maternities) from merged
where City = 'Jeza' and `Group` = 'Unknown')/
(select sum(Maternities) from merged
where Year = '2016/17') as percentage

You can do next:
select
-- divide partial sum by total
sum(if(Year = '2016/17', maternities, 0)) /
sum(if((City = 'Jeza' and `Group` = 'Unknown'), maternities, 0))
from merged;

you can also use:
select sum(Maternities)*100.0/(select sum(maternities) as total from merged
where City = 'Jeza' and Group = 'Unknown') as percent from merged
where Year = '2016/17'

select b.for_2018_19 / a.total
from ( select sum(maternities) as total
from merged
where City = 'Jeza'
and Group = 'Unknown' ) a
, ( select sum(Maternities) as for_2018_19
from merged
where Year = '2016/17'
) b

Related

Return results where no values exist for a specific column

Any guidance would be greatly appreciated please.
Aim of the statement is to read the East (x) and West (y) in the same row for the same year and month.
Not sure if I am over complicating things. I am stuck with the y as part of my statement. Currently there are no records for statement WHERE Dam_Name = 15 AND [Survey_Date] > DATEADD(yyyy,-1,getdate()) so my final results return no records.
How do I get it to still give me the list with the x values and blank for the y values?
Here is what I built.
;WITH x AS
(
SELECT [Survey_Year], [Water_Volume], DateName(month,DateAdd(month,Survey_Month,-1)) as Month
FROM Dam_Water_Levels
WHERE Dam_Name = 14 AND [Survey_Date] > DATEADD(yyyy,-1,getdate())
)
, y AS
(
SELECT
Case when count (1) >0
then (select [Survey_Year], [Water_Volume], DateName(month,DateAdd(month,Survey_Month,-1)))
else ''
END
as Month
FROM Dam_Water_Levels
WHERE Dam_Name = 15 AND [Survey_Date] > DATEADD(yyyy,-1,getdate())
Group by Survey_Year,Survey_Month, Water_Volume
)
SELECT Month = x.Month, East = x.Water_Volume, West = y.Water_Volume
FROM x
INNER JOIN y ON x.Month = y.Month
inner join Months mon on mon.Month=y.Month
order by y.Survey_Year, mon.ID;
Hope it makes sense
Regards,
Tanya
Another way I looked at it was to use this query. The down side was I had to include a column I didn't want (Intended_Month) because I needed it in my order by statement.
SELECT
Distinct a.Intended_Month as ' ', DateName(month,DateAdd(month,a.Intended_Month,-1)) as Month,
( SELECT Water_Volume from Dam_Water_Levels as y WHERE a.Survey_Year=y.Survey_Year and a.Survey_Month=y.Intended_Month and y.Dam_Name = 14) as 'East' ,
(SELECT Water_Volume from Dam_Water_Levels as x WHERE a.Survey_Year=x.Survey_Year and a.Survey_Month=x.Intended_Month and x.Dam_Name = 15) as' West'
FROM Dam_Water_Levels as a
where a.[Survey_Date] > DATEADD(yyyy,-1,getdate())
order by a.Intended_Month

GROUP_CONCAT split in different columns MYSQL

I am working with a TABLE, need logical help
This query:
SELECT
DATE_FORMAT(tran_date, '%M %Y') AS month_name,
SUM(IF(c.ctype = 4, gl.amount * -1, 0)) AS sales,
GROUP_CONCAT(DISTINCT(d.name)) AS d_name
FROM
gl_trans AS gl, company_chart_masters AS a,
company_chart_types AS t, company_chart_classes AS c, dimensions as d
WHERE
(c.ctype = 4 OR c.ctype = 5) AND
d.id = gl.dimension2_id AND
gl.account = a.account_code AND
a.account_type = t.id AND
t.class_id = c.id AND
DIMENSION2_id = gl.dimension2_id
GROUP BY
month_name
ORDER BY
month_name DESC
Produces this result:
As you can see the output of the query has 3 columns month_name, sale and pos where the pos column is separated with comma. But what I want now is to split the pos in different columns (factor matab, Rawalpindi matab, ...).
My second problem is that I also split the sale column like a split the pos column ans show sale accordingly pos wise and this sale column also shows in different columns after splitting.
Is there any other way to split the RESULT and show each value in the column and same ROW? In the same result?
Expected result:
Month_name Factor_Matab Rawalpindi_Matab
-----------------------------------------------
feb 2020 25000 78236
mar 2020 26366 82367
As I am new at stack overflow so I don't know how to show this expected result in tabular form
For get your expectation you should to use pivot table pattern:
SELECT
month_name,
-- pivot table
SUM(IF(dimension = 'Factor_Matab', sales, 0)) AS Factor_Matab,
SUM(IF(dimension = 'Rawalpindi_Matab', sales, 0)) AS Rawalpindi_Matab
FROM (
-- Select data grouped by month and dimension as tmp
SELECT
DATE_FORMAT(tran_date, '%M %Y') AS month_name,
d.name AS dimension,
SUM(IF(c.ctype = 4, gl.amount * -1, 0)) AS sales
FROM
gl_trans AS gl,
company_chart_masters AS a,
company_chart_types AS t,
company_chart_classes AS c,
dimensions as d
WHERE (c.ctype = 4 OR c.ctype = 5) AND
d.id = gl.dimension2_id AND
gl.account = a.account_code AND
a.account_type = t.id AND
t.class_id = c.id AND
DIMENSION2_id = gl.dimension2_id
GROUP BY month_name, d.name
) tmp
-- group tmp table by month
GROUP BY month_name
ORDER BY month_name DESC;

MySql - Selecting MAX & MIN and returning the corresponding rows

I trying to get the last 6 months of the min and max of prices in my table and display them as a group by months. My query is not returning the corresponding rows values, such as the date time for when the max price was or min..
I want to select the min & max prices and the date time they both occurred and the rest of the data for that row...
(the reason why i have concat for report_term, as i need to print this with the dataset when displaying results. e.g. February 2018 -> ...., January 2018 -> ...)
SELECT metal_price_id, CONCAT(MONTHNAME(metal_price_datetime), ' ', YEAR(metal_price_datetime)) AS report_term, max(metal_price) as highest_gold_price, metal_price_datetime FROM metal_prices_v2
WHERE metal_id = 1
AND DATEDIFF(NOW(), metal_price_datetime) BETWEEN 0 AND 180
GROUP BY report_term
ORDER BY metal_price_datetime DESC
I have made an example, extract from my DB:
http://sqlfiddle.com/#!9/617bcb2/4/0
My desired result would be to see the min and max prices grouped by month, date of min, date of max.. and all in the last 6 months.
thanks
UPDATE.
The below code works, but it returns back rows from beyond the 180 days specified. I have just checked, and it is because it joining by the price which may be duplicated a number of times during the years.... see: http://sqlfiddle.com/#!9/5f501b/1
You could use twice inner join on the subselect for min and max
select a.metal_price_datetime
, t1.highest_gold_price
, t1.report_term
, t2.lowest_gold_price
,t2.metal_price_datetime
from metal_prices_v2 a
inner join (
SELECT CONCAT(MONTHNAME(metal_price_datetime), ' ', YEAR(metal_price_datetime)) AS report_term
, max(metal_price) as highest_gold_price
from metal_prices_v2
WHERE metal_id = 1
AND DATEDIFF(NOW(), metal_price_datetime) BETWEEN 0 AND 180
GROUP BY report_term
) t1 on t1.highest_gold_price = a.metal_price
inner join (
select a.metal_price_datetime
, t.lowest_gold_price
, t.report_term
from metal_prices_v2 a
inner join (
SELECT CONCAT(MONTHNAME(metal_price_datetime), ' ', YEAR(metal_price_datetime)) AS report_term
, min(metal_price) as lowest_gold_price
from metal_prices_v2
WHERE metal_id = 1
AND DATEDIFF(NOW(), metal_price_datetime) BETWEEN 0 AND 180
GROUP BY report_term
) t on t.lowest_gold_price = a.metal_price
) t2 on t2.report_term = t1.report_term
simplified version of what you should do so you can learn the working process.
You need calculate the min() max() of the periods you need. That is your first brick on this building.
you have tableA, you calculate min() lets call it R1
SELECT group_field, min() as min_value
FROM TableA
GROUP BY group_field
same for max() call it R2
SELECT group_field, max() as max_value
FROM TableA
GROUP BY group_field
Now you need to bring all the data from original fields so you join each result with your original table
We call those T1 and T2:
SELECT tableA.group_field, tableA.value, tableA.date
FROM tableA
JOIN ( ... .. ) as R1
ON tableA.group_field = R1.group_field
AND tableA.value = R1.min_value
SELECT tableA.group_field, tableA.value, tableA.date
FROM tableA
JOIN ( ... .. ) as R2
ON tableA.group_field = R2.group_field
AND tableA.value = R2.max_value
Now we join T1 and T2.
SELECT *
FROM ( .... ) as T1
JOIN ( .... ) as T2
ON t1.group_field = t2.group_field
So the idea is if you can do a brick, you do the next one. Then you also can add filters like last 6 months or something else you need.
In this case the group_field is the CONCAT() value

How can I increase the number of years in SQL and in SSRS report?

I have a forecast algorithm
WITH CTE_AllIDs AS
(
SELECT TOP 22 ID = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM sys.columns
)
SELECT
c.ID
,OrderMonth = CASE WHEN r.ID IS NOT NULL
THEN r.OrderMonth
-- elaborate function to get the short month name and year
ELSE ordermonth + 1
END
,OrderQuantity
,Trend
,Forecast = CASE WHEN Trend IS NOT NULL AND c.ID <> (SELECT MAX(ID) FROM #Temp_Regression)
THEN NULL
-- For the last actual value (September in this example), we want forecast to have the same
-- value as the trendline (instead of NULL). This prevents a gap in the line charts in SSRS.
WHEN Trend IS NOT NULL AND c.ID = (SELECT MAX(ID) FROM #Temp_Regression)
THEN Trend
-- If trend is not found, it means we can calculate a forecast.
-- However, we also need to check if the month for which we calculate the forecast comes after
-- the actual values. Suppose we don't have values for January, then we don't want to calculate
-- a forecast for January as well. Only for the last 3 months of the year in this example.
WHEN Trend IS NULL AND c.ID > (SELECT MAX(ID) FROM #Temp_Regression)
THEN (#slope * (c.ID % 100)) + #intercept
ELSE NULL
END
FROM CTE_AllIDs c
LEFT JOIN #Temp_Regression r ON c.ID = r.ID;
The results
How can I do this in the values of the OrderMoth columns increase by one the? 2023, 2024, etc.
Thanks.
Your Else in your Case Statement will always contain Null. Try this.
ELSE (Select Max(OrderMonth) From #Temp_Regression) + ((C.ID) - (Select Max(ID) From #Temp_Regression))

SSRS Matrix percentages

Here's the report:
This is how I got the percentages for column the '%Change of most recent year".
=((Last(Fields!Quantity.Value,"Child") - First(Fields!Quantity.Value)) / First(Fields!Quantity.Value))`
= ((54675 - 55968)/55968 ) = -2.31%'
= ((54675 - 57849)/57849) = -5.49%'
It will always take the first year '2012' in this case and get the percentages against each other year. If I enter the years 2005,2004,2003,2002,2001 it will always take the first year and do a percentages against each additional year. 2005 to 2004, 2005 to 2003, 2005 to 2002 and so on. I can have as many as 2 column (year) to many columns.
I need to do it for the Total and Subtotal but it won't work because it's in a different scope.
data is = row Child group
Sub Total: = row Parent group
Total: = row Total group
Year = Column Period group
Query use to get result.
SELECT MEMBERSHIP_CODE
, PERIOD, COUNT(DISTINCT ID) AS Distinct_ID
, SUM(QUANTITY) AS Quantity
, '01-Personal' AS Child
, '01-Overall' AS Parent
, 'Total' as Total
FROM vf_Sshot AS vfs
INNER JOIN vProd AS vP ON vfs.PRODUCT_CODE = vP.PRODUCT_CODE
INNER JOIN vMem_Type vMT on vMT.Member_Type = vfs.Member_Type
WHERE (PERIOD IN ( (SELECT Val from dbo.fn_String_To_Table(#Periods,',',1))))
AND (vMT.MEMBER_TYPE NOT IN ('a','b','c'))
AND (vfs.STATUS IN ( 'A', 'D', 'C'))
AND (MEMBERSHIP_CODE NOT IN ('ABC', 'DEF' ))
and vP.PROD_TYPE in ('DUE','MC','SC')
and vMT.Member_Record = '1'
GROUP BY MEMBERSHIP_CODE, PERIOD
Any ideas?
How would I produce this output?
TOTAL: 57,573 58,941 57,573 61,188 57,573 61,175 57,175
This is the easiest way of solving your problem. In your query, identify the sum for the latest period on a separate column (you can transform your query into a CTE, so that you don't have to change your base query a lot):
WITH query AS (
SELECT MEMBERSHIP_CODE
, PERIOD, COUNT(DISTINCT ID) AS Distinct_ID
, SUM(QUANTITY) AS Quantity
, '01-Personal' AS Child
, '01-Overall' AS Parent
, 'Total' as Total
...
UNION
SELECT
...
)
SELECT
A.MEMBERSHIP_CODE,
A.PERIOD,
A.Distinct_ID,
A.Child,
A.Parent,
A.Total,
A.Quantity,
B.Quantity AS LastPeriodQuantity
FROM
query A INNER JOIN
(SELECT *, ROW_NUMBER() OVER(PARTITION BY MEMBERSHIP_CODE, Distinct_ID, Child, Parent ORDER BY PERIOD DESC) as periodOrder FROM query) B ON
A.MEMBERSHIP_CODE = B.MEMBERSHIP_CODE AND
A.DISTINCT_ID = B.DISTINCT_ID AND
A.Parent = B.Parent AND
A.Child = B.Child AND
A.Total = B.Total AND
B.PeriodOrder = 1
And then on all your totals/subtotals/columns you will be accessing a column that is being grouped/filtered by the same rules than your denominator. Your expression can remain, for all cells, something like this:
=(Fields!LastPeriodQuantity.Value - Fields!Quantity.Value) / Fields!Quantity.Value