Summary HackerRank Problem
(1) Draw Triangle 1
P(5) :
* * * * *
* * * *
* * *
* *
*
This is example and i have to make this P(20)
WITH RECURSIVE stars (n,star) AS(
SELECT 39,LEFT('* * * * * * * * * * * * * * * * * * * *',39)
UNION ALL
SELECT n-2,LEFT('* * * * * * * * * * * * * * * * * * * *',n-2)
FROM stars
WHERE n>1
)
SELECT star
FROM stars
I solved question of Draw the Triangle 1 in this way.
(2) Draw Triangle 2
P(5):
*
* *
* * *
* * * *
* * * * *
This is example and i have to make this P(20)
However, this does not work in Draw THE Triangle 2
WITH RECURSIVE stars (n,star) AS(
SELECT 1, LEFT('* * * * * * * * * * * * * * * * * * * *',1)
UNION ALL
SELECT n+2, LEFT('* * * * * * * * * * * * * * * * * * * *',n+2)
FROM stars
WHERE n<38
)
SELECT star
FROM stars
WITH RECURSIVE stars (n,star) AS(
SELECT 1,'*'
UNION ALL
SELECT n+1, CONCAT(star,' *')
FROM stars
WHERE n<20
)
SELECT star
FROM stars
I tried using LEFT() by changing the number just like Triange 1, but the HackerRank site showed a message like 'ERROR 1406 (22001) at line 1: Data too long for column 'star' at row 1' In my personal mysql, I only got OK, but I couldn't see the result table.
If the data is too long and it is an error, shouldn't I meet the same error in the first problem?
Is there something I don't know ?
Take a good look at outputs of queries for "triangle 1" and "triangle 2".
What is the difference? That's right, rows for the "triangle 2" query are in reverse order.
Which value in the query for "triangle 1" defines the order of rows? That's right, it's n.
How can I modify the query for "triangle 1" so that it outputs rows in reverse order? That's right, since the value of n in the first row is 39 and the last one is 1 (the rows are ordered by n in descending order), just reverse rows order by adding ORDER BY n.
So the query for "triangle2" should look like
WITH RECURSIVE stars(n, star) AS(
SELECT 39, LEFT('* * * * * * * * * * * * * * * * * * * *', 39)
UNION ALL
SELECT n-2, LEFT('* * * * * * * * * * * * * * * * * * * *', n-2)
FROM stars
WHERE n > 1
)
SELECT star
FROM stars
ORDER BY n
Just check it
In mysql I am calculating all the points between two zip codes and that's working fine for me. Now I want update that query to join an additional table, but I am getting an error. Here is the query please have a look:
SELECT *
FROM users
INNER JOIN
(SELECT *,
ACOS(
COS(RADIANS(30.7261629))
* COS(RADIANS(lat_collection))
* COS(RADIANS(76.7596221) - RADIANS(`long_collection`))
+ SIN(RADIANS(30.7261629))
* SIN(RADIANS(lat_collection))
) * 3956 AS `distance`
FROM quote q
WHERE lat_collection BETWEEN 30.7261629 - (30 / 69) AND 30.3345816 + (30 / 69)
AND `long_collection` BETWEEN 76.7596221 - (30 / (69 * COS(RADIANS(30.7261629)))) AND 78.0537813 + (30 / (69* COS(RADIANS(30.7261629))))
) AS u
ON q.user_id=u.id
WHERE `distance` < 30
I need to join four-five table in the same query; how can I do that? I am getting an error when trying to join the tables (I have two zip codes and then I calculate lat long for both the zip codes).
You are using an alias in where condition .. this is not allowed you must reuse the full code instead of alias
SELECT *
FROM users inner join (
SELECT *, 3956 * ACOS(COS(RADIANS(30.7261629)) * COS(RADIANS(lat_collection)) * COS(RADIANS(76.7596221) -
RADIANS(`long_collection`))
+ SIN(RADIANS(30.7261629)) * SIN(RADIANS(lat_collection))) AS `distance`
FROM quote q
WHERE lat_collection BETWEEN 30.7261629 - (30 / 69) AND 30.3345816 + (30 / 69)
AND `long_collection` BETWEEN 76.7596221 - (30 / (69 * COS(RADIANS(30.7261629)))) AND 78.0537813 + (30 / (69* COS(RADIANS(30.7261629))))
) as u on users.id=u.user_id
WHERE (3956 * ACOS(COS(RADIANS(30.7261629)) * COS(RADIANS(lat_collection)) * COS(RADIANS(76.7596221) - RADIANS(`long_collection`))
+ SIN(RADIANS(30.7261629)) * SIN(RADIANS(lat_collection)))) < 30
I have a table with columns:
s_Id (primary int), sup_type (int), sup_date (datetime), sup_req (int)
Values in sup_type so far range from 0-5.
How can I extract the most recent entry (by sup_date) of each sup_type (0-5).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* s_Id * sup_type * sup_date * sup_req *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 1 * 0 * 2012-06-15 10:13:21 * 4 *
* 2 * 0 * 2012-06-15 11:22:01 * 4 *
* 3 * 1 * 2012-06-15 13:23:32 * 4 *
* 4 * 2 * 2012-06-16 08:04:29 * 4 *
* 5 * 1 * 2012-06-16 16:23:24 * 4 *
* 6 * 1 * 2012-06-17 13:14:05 * 4 *
* 7 * 3 * 2012-06-18 13:37:55 * 4 *
* 8 * 4 * 2012-06-19 13:21:52 * 4 *
* 9 * 4 * 2012-06-20 16:15:19 * 4 *
* 10 * 5 * 2012-06-20 16:17:37 * 4 *
* 11 * 0 * 2012-06-20 16:21:53 * 4 *
* 12 * 1 * 2012-06-20 16:28:13 * 4 *
* 13 * 3 * 2012-06-21 12:23:29 * 4 *
* 14 * 3 * 2012-06-22 07:26:41 * 4 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
I want to extract
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* s_Id * sup_type * sup_date * sup_req *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 4 * 2 * 2012-06-16 08:04:29 * 4 *
* 9 * 4 * 2012-06-20 16:15:19 * 4 *
* 10 * 5 * 2012-06-20 16:17:37 * 4 *
* 11 * 0 * 2012-06-20 16:21:53 * 4 *
* 12 * 1 * 2012-06-20 16:28:13 * 4 *
* 14 * 3 * 2012-06-22 07:26:41 * 4 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Thanks.
SELECT
b.*
FROM
(
SELECT sup_type, MAX(sup_date) AS maxsupdate
FROM tbl
GROUP BY sup_type
) a
INNER JOIN
tbl b ON
a.sup_type = b.sup_type AND
a.maxsupdate = b.sup_date
ORDER BY
b.s_Id
I have a table where I can find the same parameter in subsequent rows (See Example A). I need a query to select only the rows where the value is different from the previous row (See Example B), something like
SELECT * FROM tableName WHERE Par(id)!=Par(id-1)
It shouldn't be difficult but I'm new to MySQL (and databases in general) and I haven't found an command or an example for this.
Example A Example B
********* *********
*ID *Par* **ID*Par*
********* *********
*1 * a * *5 * a *
*2 * a * *6 * g *
*3 * a * *7 * f *
*4 * a * *8 * d *
*5 * a * *9 * f *
*6 * g * *10 * h *
*7 * f * *11 * j *
*8 * d * *12 * f *
*9 * f * *17 * f *
*10 * h * *18 * d *
*11 * j * *19 * s *
*12 * f * *20 * g *
*13 * f * *21 * t *
*14 * f * *22 * g *
*15 * f *
*16 * f *
*17 * f *
*18 * d *
*19 * s *
*20 * g *
*21 * t *
*22 * g *
Try this:
SELECT t.id,t.par FROM your_table t
WHERE t.par <>
(SELECT par FROM your_table
WHERE id = t.id + 1)
SELECT DISTINCT Par
FROM table_name
http://www.w3schools.com/sql/sql_distinct.asp
I'm using a slightly-modified version of the geocoded gem which returns this query when I call near on my model (calling Deal.near(southwest), where southwest is an array of geo coordinates):
SELECT
deals.*,
3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((37.772476604436974 - addresses.lat) * PI() / 180 / 2), 2) + COS(37.772476604436974 * PI() / 180) * COS(addresses.lat * PI() / 180) * POWER(SIN((-122.42336332798004 - addresses.lng) * PI() / 180 / 2), 2) )) AS distance,
CAST(DEGREES(ATAN2( RADIANS(addresses.lng - -122.42336332798004), RADIANS(addresses.lat - 37.772476604436974))) + 360 AS decimal) % 360 AS bearing
FROM "deals"
INNER JOIN "companies" ON "companies"."id" = "deals"."company_id"
INNER JOIN "addresses" ON "addresses"."addressable_id" = "companies"."id" AND "addresses"."addressable_type" = 'Company'
WHERE (
addresses.lat BETWEEN 37.483013038215276 AND 38.06194017065867
AND addresses.lng BETWEEN -122.78956461309022 AND -122.05716204286986
)
GROUP BY
deals.id,
deals.created_at,
deals.updated_at,
deals.active,
deals.company_id,
deals.title,
deals.limitations,
deals.redemption_count,
addresses.lat,
addresses.lng
HAVING 3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((37.772476604436974 - addresses.lat) * PI() / 180 / 2), 2) + COS(37.772476604436974 * PI() / 180) * COS(addresses.lat * PI() / 180) * POWER(SIN((-122.42336332798004 - addresses.lng) * PI() / 180 / 2), 2) )) <= 20
ORDER BY 3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((37.772476604436974 - addresses.lat) * PI() / 180 / 2), 2) + COS(37.772476604436974 * PI() / 180) * COS(addresses.lat * PI() / 180) * POWER(SIN((-122.42336332798004 - addresses.lng) * PI() / 180 / 2), 2) )) ASC
My issue is that this will return multiple Deal records if that Deal's company has multiple Addresses, which I don't want.
In MySQL, I could just omit address.lat, address.lng in the GROUP_BY clause and it will properly group the records, but I can't do this in PostgreSQL.
I know I could wrap the whole query above in another SELECT and GROUP_BY, like this:
SELECT
id, created_at, updated_at, active, title, punches_to_complete, company_id, description, lat, lng, MIN(distance), bearing
FROM ( ... ) AS t
GROUP BY company_id
... where the ellipsis is the query from above. That (I believe) should get me the desired result in both MySQL and PostgreSQL.
The only problem is that I have no idea how to write this in ARel!
I had tried the following, a la this tip from the ARel guru, but I couldn't really make it work quite right (calling to_sql as the OP had said fixed his issue escapes the quotes, which freaks PostgreSQL out).
Can anyone help me with this???
UPDATE:
I've managed to get this done with an additional scope, like so:
scope :nearest, lambda { |coords|
subquery = "(#{Deal.near(coords).to_sql}) AS t1"
columns = Deal.columns.map{ |c| c.name }.join(',')
Deal.select(columns)
.select('MIN(distance) AS distance')
.from(subquery)
.group(columns)
.order('distance ASC')
}
However, this totally breaks chainability, as now I cannot call something like current_user.deals.nearest(coords), since that tags on an additional WHERE deals.user_id = 1 to the query outside of the subselect. I tried compensating for this by moving this logic into a class method and blanking the wheres clause on the SelectManager manually, like this:
def self.nearest(coords)
subquery = "(#{Deal.near(coords).to_sql}) AS t1"
columns = Deal.columns.map{ |c| c.name }.join(',')
query = Deal.select(columns)
.select('MIN(distance) AS distance')
.from(subquery)
.group(columns)
.order('distance ASC')
query.arel.ast.cores[0].wheres = []
query
end
... but that doesn't seem to work either: the additional WHERE clause is still appended:
Failure/Error:
#user.deals.nearest(southwest).first.distance.to_f.round(2).should ==
ActiveRecord::StatementInvalid:
Mysql2::Error: Unknown column 'deals.user_id' in 'where
clause': SELECT id,created_at,updated_at,user_id,company_id,
MIN(distance) AS distance FROM (SELECT deals.*, 3958.755864232 * 2 *
ASIN(SQRT(POWER(SIN((37.772476604436974 - addresses.lat) * PI() / 180
/ 2), 2) + COS(37.772476604436974 * PI() / 180) * COS(addresses.lat *
PI() / 180) * POWER(SIN((-122.42336332798004 - addresses.lng) * PI() /
180 / 2), 2) )) AS distance, CAST(DEGREES(ATAN2( RADIANS(addresses.lng
- -122.42336332798004), RADIANS(addresses.lat - 37.772476604436974)))
+ 360 AS decimal) % 360 AS bearing FROM deals INNER JOIN companies
ON companies.id = deals.company_id INNER JOIN addresses ON
addresses.addressable_id = companies.id AND
addresses.addressable_type = 'Company' WHERE deals.user_id =
26 AND (addresses.lat BETWEEN 37.483013038215276 AND 38.06194017065867
AND addresses.lng BETWEEN -122.78956461309022 AND -122.05716204286986)
GROUP BY
deals.id,deals.created_at,deals.updated_at,deals.user_id,deals.company_id,
addresses.lat, addresses.lng HAVING 3958.755864232 * 2 *
ASIN(SQRT(POWER(SIN((37.772476604436974 - addresses.lat) * PI() / 180
/ 2), 2) + COS(37.772476604436974 * PI() / 180) * COS(addresses.lat *
PI() / 180) * POWER(SIN((-122.42336332798004 - addresses.lng) * PI() /
180 / 2), 2) )) <= 20 ORDER BY 3958.755864232 * 2 *
ASIN(SQRT(POWER(SIN((37.772476604436974 - addresses.lat) * PI() / 180
/ 2), 2) + COS(37.772476604436974 * PI() / 180) * COS(addresses.lat *
PI() / 180) * POWER(SIN((-122.42336332798004 - addresses.lng) * PI() /
180 / 2), 2) )) ASC) AS t1 WHERE deals.user_id = 26 GROUP BY
id,created_at,updated_at,user_id,company_id ORDER BY distance ASC
LIMIT 1
Is what I'm trying to do even possible with ARel? The additional scopes above feel really dirty to me (parsing the subquery to raw SQL? I thought ARel was supposed to make it so I never did that!)
Related question: Can ARel formulate cross-db queries for CTEs (Common Table Expressions)?