SQLについては素人なのでググりながらやりました。
RDBMSはMySQLを選択しました(本当はSQLiteかPostgreSQLを選びたかったのですが,HackerRankがDB2, MySQL, Oracle, SQL Serverしか対応していなかったので)。
The Blunder
お給料の平均値を計算したかったのですが,Samanthaさんはお給料を入力するときに0を入力できませんでした。正しい平均値と,Samanthaが計算した平均値の差を求めてceilしてください。
最初の問題からかなりググってました。Samanthaさんの入力を計算する (10203 → 123) には,SalaryをCASTで文字列にして,REPLACEで'0'を消せばよさそうですね。
今気づいたんですが,AVGに文字列を渡すと勝手に数値型に変換されるんですね…(こわい)
SELECT CEIL( ABS(AVG(REPLACE(CAST(Salary AS CHAR), '0', '')) - AVG(Salary)) ) FROM Employees;
Type of Triangle
三角形の三辺の長さが与えられるので,どんな三角形か出力してください。
CASE WHENをゴリゴリ書きました
SELECT (CASE WHEN A >= B + C OR B >= C + A OR C >= A + B THEN 'Not A Triangle' WHEN A = B AND B = C THEN 'Equilateral' WHEN A = B OR B = C OR C = A THEN 'Isosceles' ELSE 'Scalene' END) FROM Triangles;
Higher Than 75 Marks
点数が75点よりも大きい人を,名前の後ろの三文字で並べ替えてください。
このあたりから,SQLの予約語を大文字で書くのが面倒になってきたので小文字で書き始めました。
部分文字列を取得する関数はRDBMSによってSUBSTRだったりSUBSTRINGだったりするようです。MySQLではSUBSTRINGでした。
SUBSTRING:文字列から位置を指定して文字列を取り出す
文字列長はCHAR_LENGTHで取れるようです。たぶん文字コード絡みで面倒なことがあるんだろうな…
select Name from Students where Marks > 75 order by substring(Name, char_length(Name)-2), Id;
The PADS
名前+職業の頭文字を表示した後に,それぞれの職業の人が何人いるか表示してください。
printfみたいな関数がないので,CONCAT関数で原始的に繋げるしかなくて残念。
select concat(Name, '(', substring(Occupation, 1, 1), ')') from Occupations order by Name; select concat('There are total ', count(*), ' ', lower(Occupation), 's.') from Occupations group by Occupation order by count(*);
Occupations
例に示すような表を作ってください
全くわからない… FOR文使えないとダメなんでしょうか?
The Report
点数 (Marks) と,それに対応するGradeのMin_MarkとMax_Markの情報が与えられるので,Gradeが8以上の人はGradeで降順,Nameで昇順に,Gradeが8未満の人はGradeで降順,Marksで昇順に並べて,名前はNULLでマスクしてください。
オリジナルの問題文からは,Gradeが8割未満の人もGradeで降順に並べないといけないのかどうか読み取りにくいです。
同じJOIN句を繰り返して書いてしまったので反省。おそらく繰り返し書かずに済む方法があると思うのですが,どうなんでしょうか?
select Name, Grade, Marks from Students join Grades on Marks between Min_Mark and Max_Mark where Grade >= 8 order by Grade desc, Name; select NULL, Grade, Marks from Students join Grades on Marks between Min_Mark and Max_Mark where Grade < 8 order by Grade desc, Marks;
Binary Search Tree
木のノードの情報が (ノード番号, 親のノード番号) のリストとして与えられるので,それぞれのノードが葉, 根, それ以外のどれであるか表示してください。
特に指定はありませんが,ノード番号で降順に並べないとダメです。
select N, (case when isnull(P) then 'Root' when (select count(*) from BST as BST2 where BST2.P = BST.N) = 0 then 'Leaf' else 'Inner' end) from BST order by N;
Symmetric Pairs
ある関数Fがあり,Y=F(X)です。X_1=Y_2 && Y_1=X_2 となるような組をSymmetric Pairと呼ぶことにします。Symmetric Pairを列挙してください。
テストケースが合いませんでした。
サンプルに{x=20, y=20}というタプルが2つあるのだけど,RDBって全属性が同じタプルを持っていてはいけなかったのでは?
Projects
プロジェクトがStart_DateとEnd_Dateの組として与えられます。one.End_Date=other.Start_Dateとなっている2つのプロジェクトは同じプロジェクトとみなします。そのようなプロジェクトをまとめあげて表示してください。
one.End_Date=other.Start_Date
という条件でグループ分けする方法が分からなくて解けませんでした。誰か教えてください。
Placements
その人のbest friendよりも給料が低い人を列挙してください。
IDという属性名があまり考えられずに乱用されている例ですよね。
select Students.Name from Students join Friends on Students.ID = Friends.ID join Packages as P1 on Students.ID = P1.ID join Packages as P2 on Friends.Friend_ID = P2.ID where P1.Salary < P2.Salary order by P2.Salary;