Between clause doesn't work - mysql

Trying to set amount range like 0 to 9 10 to 19 ... 50 - 99 but when done individually i.e. a.Amount >50 returns data rows and similarly a.Amount >100 returns data rows but the follwing returns null rows. Please help deadline is near! The Amount is a varchar data type.
SELECT DATE_FORMAT((STR_TO_DATE(a.TRANSACTION_DATE,'%d.%m.%Y')), '%Y%m') mnt,
COUNT(DISTINCT a.CUSTOMER_ID) totalNum
FROM credittx a
WHERE a.COUNTRY = 'Germany'
AND a.AMOUNT BETWEEN 100 AND 50
GROUP BY DATE_FORMAT((STR_TO_DATE(a.TRANSACTION_DATE,'%d.%m.%Y')),'%Y%m')

The range is from-to
do BETWEEN 50 AND 100

Seems to me that you must have between 50 AND 100. Not 100 AND 50.
SELECT
DATE_FORMAT((STR_TO_DATE(a.TRANSACTION_DATE,'%d.%m.%Y')), '%Y%m') mnt,
COUNT(DISTINCT a.CUSTOMER_ID) totalNum
FROM credittx a
WHERE a.COUNTRY = 'Germany'
AND a.AMOUNT BETWEEN 50 AND 100
GROUP BY DATE_FORMAT((STR_TO_DATE(a.TRANSACTION_DATE,'%d.%m.%Y')),'%Y%m')

As mentioned in the comment that 50 is less than 100 so please change:
AND a.AMOUNT BETWEEN 100 AND 50
to:
AND a.AMOUNT BETWEEN 50 AND 100

Related

MySql Select - row subtract previous row

I'm trying to extract stats from DB.
Table's structure is:
UpdatedId product_name revenue
980 Product1 1000
975 Product1 950
973 Product1 900
970 Product1 800
965 Product21 1200
So revenue = previous revenue + new revenue.
In order to make graphs, the goal is to get the output for Product1 like this
UpdateId Difference
980 50
975 50
973 100
970 0
I tried this query but MySQL gets stuck :)
select a.product_name, a.revenue, b.revenue, b.revenue- a.revenue as difference from updated_stats a, updated_stats b where a.product_name=b.product_name and b.revenue= (select min(revenue) from updated_stats where product_name=a.product_name and revenue > a.revenue and product_name= 'Product1')
Could you please tell me, how it should be queried? Thanks.
I would do this with a correlated subquery:
select u.*,
(select u.revenue - u2.revenue
from updated_stats u2
where u2.product_name = u.product_name and
u2.updatedid < u.updatedid
order by u2.updatedid desc
limit 1
) as diff
from updated_stats u;
Note: This returns NULL instead of 0 for 970. That actually makes more sense to me. But you can use COALESCE() or a similar function to turn it into a 0.
If updated_stats is even moderately sized, you will want an index on updated_status(product_name, updated_id, revenue). This index covers the subquery.

MySQL: Range based on rows in external table

I am using MySQL to solve this problem. I need to give points to a user based on the total time spent by him on a question. I have calculated the time spent by the user. Let's say it is in user_time table.
user_id question_id time_spent
1 1 7
1 2 50
2 1 11
My points are range based:
[0-10) seconds: 100 points,
[10-20) seconds: 300 points,
[20-30) seconds: 500 points,
[30, inf): 1000 points
Exact 10 seconds will fetch me 300 points. Though, the changes of an exact number would be low given that I am computing from the system clock difference.
This information is currently scored in an external table points_table
time_spent points
0 100
10 300
20 500
30 1000
I need a query which finds out which range the seconds belong to and give me that result.
user_id question_id points
1 1 100
1 2 1000
2 1 300
I tried thinking of different type of joins but couldn't think of one which will answer this specific requirement.
I think the easiest approach is a correlated subquery. Something like this:
select ut.*,
(select pt.points
from points_table pt
where pt.time_spent <= ut.time_spent
order by pt.time_spent desc
limit 1
) as points
from user_time ut
Try this:
SELECT ut.user_id, ut.time_spent, A.points
FROM user_time ut
INNER JOIN (SELECT p1.time_spent AS time_spent1,
p2.time_spent AS time_spent2,
p1.points
FROM points_table p1
INNER JOIN points_table p2 ON p1.time_spent < p2.time_spent
GROUP BY p1.time_spent
) AS A ON ut.time_spent BETWEEN A.time_spent1 AND A.time_spent2
For another take on this, you could achieve the same result without having the points table:
SELECT *,
CASE
WHEN time_spent >= 30 THEN 1000
WHEN time_spent >= 20 THEN 500
WHEN time_spent >= 10 THEN 300
ELSE 100
END 'Points'
FROM user_time;

Missing records from one table in SQL Server 2008R2

Table 1:
Date PlacementID CampaignID Impressions
04/01/2014 100 10 1000
04/01/2014 101 10 1500
04/01/2014 100 11 500
Table 2:
Date PlacementID CampaignID Cost
04/01/2014 100 10 5000
04/01/2014 101 10 6000
04/01/2014 100 11 7000
04/01/2014 103 10 8000
When I have joined this table using Full Join and Left Join statement, I am not able to get uncommon record which is last row in table2 that display PlacementID 103 and campaignID 10 and Cost 8000. However I have searched all raw data and file but this missing records are not common between two sources. However, I want to include this records in final table. How can I do that? This two table are two different source and I have got results only common records.
Moreover, when I found out that missing value is exact value that are required in final figure so want to include every thing. I am including my SQL script below:
SELECT A.palcementid,
A.campaignid,
A.date,
Sum(A.impressions) AS Impressions,
Sum(CASE
WHEN C.placement_count > 1 THEN ( B.cost / C.placement_count )
ELSE B.cost
END) AS Cost
FROM table1 A
FULL JOIN table2 B
ON A.placementid = B.placementid
AND A.campaignid = B.campaignid
AND A.date = B.date
LEFT JOIN (SELECT Count(A.placementid) AS Placement_Count,
placementid. campaignid,
date
FROM table1
GROUP BY placementid,
campaignid,
date) c
ON A.placementid = C.placementid
AND A.campaignid = C.campaignid
AND A.date = C.date
GROUP BY A.placementid,
A.campaignid,
A.date
I am dividing Cost by placement because in source the cost was allocated for one placement only and one time so I have to divide those because in actual table the same Placementid repeat more than 1 times on same date.
As you didn't provide any expected output I guessing here but if the result you want is this:
PlacementID CampaignID Date Impressions Cost
----------- ----------- ----------------------- ----------- -----------
100 10 2014-04-01 02:00:00.000 1000 5000
100 11 2014-04-01 02:00:00.000 500 7000
101 10 2014-04-01 02:00:00.000 1500 6000
103 10 2014-04-01 02:00:00.000 NULL 8000
Then the following query should do it:
SELECT COALESCE(A.PlacementID,b.placementid) AS PlacementID,
COALESCE(A.campaignid, b.campaignid) AS CampaignID,
COALESCE(A.date, b.date) AS [Date],
SUM(A.impressions) AS Impressions,
SUM(CASE
WHEN C.placement_count > 1 THEN ( B.cost / C.placement_count )
ELSE B.cost
END ) AS Cost
FROM table1 A
FULL JOIN table2 B
ON A.[PlacementID] = B.placementid
AND A.campaignid = B.campaignid
AND A.date = B.date
LEFT JOIN (SELECT COUNT(PlacementID) AS Placement_Count,
placementid, campaignid,
date
FROM table1
GROUP BY placementid,
campaignid,
date) c
ON A.[PlacementID] = C.placementid
AND A.campaignid = C.campaignid
AND A.date = C.date
GROUP BY COALESCE(A.PlacementID, B.PlacementID),
COALESCE(A.campaignid, b.campaignid),
COALESCE(A.date, b.date)
Sample SQL Fiddle

MySql JOIN on most recent start_date?

I have two tables, one with transactions (with date). The other with a percentage and date the percentage it went into effect (assume 00:00:00). The percentage remains in effect until a new percent goes into effect. I need to join on the percentage that was in effect when the transaction happened.
transactions_table
event_date amount
2011-01-01 230
2011-02-18 194
2011-03-22 56
2011-04-30 874
percent_table
effective percent
2010-12-30 15
2011-03-05 25
2011-04-12 30
The result I'm looking for is:
event_date amount percent
2011-01-01 230 15
2011-02-18 194 15
2011-03-22 56 25
2011-04-30 874 30
I've tried:
SELECT t.event_date, t.amount, p.percent
FROM transactions_table AS t
LEFT JOIN percent_table AS p ON t.event_date >= p.effective
ORDER BY `t`.`event_date` DESC LIMIT 0 , 30;
That gives me, seemingly random percentages. It seems to me like I need to get the greatest date >= p.effective, not just any random date >= p.effective.
I tried:
SELECT t.event_date, p.percent
FROM bedic_sixsummits_transactions AS t
LEFT JOIN bedic_sixsummits_percent AS p ON MAX(t.event_date >= p.effective)
ORDER BY `t`.`event_date` DESC LIMIT 0 , 30
but MySQL just laughed at my feeble attempt.
How can I do this?
SELECT t.event_date, t.amount, p.percent
FROM bedic_sixsummits_transactions AS t
LEFT JOIN bedic_sixsummits_percent AS p
ON p.effective =
( SELECT MAX( p2.effective ) FROM bedic_sixsummits_percent AS p2
WHERE p2.effective <= t.event_date
)
ORDER BY t.event_date DESC LIMIT 0 , 30
Even more simpler and with no subquery:
SELECT event_date, amount, MAX(_percent) as _percent
FROM transactions_table
LEFT JOIN percent_table p1 ON event_date >= effective
GROUP BY event_date, amount
ORDER BY event_date;
http://sqlfiddle.com/#!3/e8ca3/17/0
Note that it is possible because of the business model involved. If you wan't to retrieve other fields of the percent_table it won't be appropriate anymore :/

how to select Count of Ranges from mysql table?

i have a table t_points in mySql like example in below.
Name Surname Point
Joe Arnold 120
Michale Black 250
Masha Petrova 300
Natalie Jackson 120
John Turo 200
Bona Meseda 250
Zeyda Nura 150
Zanura Bohara 60
Shaheen Boz 360
Abbas Murat 160
Keira Black 230
Tom Robinson 480
Fred Balka 490
Semia Hudovi 90
Sona Bahari 60
i want to write a query which will display the count of point ranges. Point ranges are like this: point between 0 and 100, 101 and 200, 201 and 300, 301 and 400.
Result must be like below
0_100 101_200 201_300 301_400
3 5 4 3
i think u understand what i want to say. So which query i have to use for this result?
Thanks.
select
count(CASE WHEN point BETWEEN 0 AND 100 THEN 1 END) as count0_100,
count(CASE WHEN point BETWEEN 101 AND 200 THEN 1 END) as count101_200,
count(CASE WHEN point BETWEEN 201 AND 300 THEN 1 END) as count201_300,
...
from
t_poits
Something like that:
select count(*) as count, abs(point/100) as range
from t_poits
group by abs(point/100)
set #range = 500;
select floor(field1/#range)*#range as `from`,(ceil(field1/#range)+if(mod(field1,#range)=0,1,0))*#range as `to`, count(field1)
from table1
group by 1,2
order by 1,2;
You can group points column and do some math operation to specify range. Based on that you can count number of records.
Like..
SELECT concat( 101 * round( Point /101 ) , '-', 101 * round( Point /101 ) +100 ) AS `range` , count( * ) AS `result`
FROM t_points
GROUP BY 1
ORDER BY Point
I hope it will work for you.
select
concat(floor(Point/100),'01_',ceil(Point/100),'00') as ind,
count(*) as cnt
from t group by ind order by ind asc;