Niuke SQL [一般的なインタビューを手作業で細断した SQL]

筆記試験問題66:ニウケへの各人の最終ログイン日(1)

  • 詳細説明: 各ユーザーの最終ログイン日をクエリする SQL ステートメントを作成し、user_id で昇順に並べ替えてください。

問題解決のアイデア

  • ユーザー ID ごとにグループ化し、最大ログイン時間を取得します

ソースコード

select user_id, max(date)
from login
group by user_id
order by user_id

筆記試験問題67:ニウケへの各人の最終ログイン日(2)

  • 詳細説明: 各ユーザーの最終ログイン日、ユーザー名、ユーザーが使用しているデバイス名をクエリする SQL ステートメントを記述してください。クエリ結果はユーザー名の昇順にソートされます。

問題解決のアイデア

  • ユーザー名はユーザー テーブルに、デバイス名はクライアント テーブルに、ログイン日はログイン テーブルにあります。
  • ログインとクライアントは client_id に依存して接続し、ログインとユーザーは user_id に依存します

ソースコード

select u.name, c.name, date
from login l
         join user u on l.user_id = u.id
         join client c on l.client_id = c.id
where (l.user_id, l.date) in (
    select user_id, max(date)
    from login
    group by user_id
)
order by u.name;

筆記試験問題68:新受者ごとの最新ログイン日(3) 【継続率】**

  • 新規ログインユーザーの翌日の継続率、つまり1日目ログイン後、2日目に再度ログインする確率を問い合わせるSQL文を記述してください。小数点以下3桁(四捨五入)で保存してください。 3桁以降)

問題解決のアイデア

  • 翌日の継続率: (初日にログインした新規ユーザーと 2 日目にもログインしたユーザー) / (合計ユーザー)

  • まず合計ユーザーを取得します

    select count(distinct user_id) from login

  • 次に、初日にログインしたユーザーを見つけます

    select user_id,min(date) from login group by user_id

  • 同時に、翌日もログインしたユーザーも検索します。

    select user_id,date_add(min(date),interval 1 day) from login group by user_id

ソースコード

select round(count(user_id) / (select count (distinct user_id) from login), 3)
from login
where (user_id, date) in (
    select user_id, date_add(min(date), interval 1 day)
    from login
    group by user_id
);

補足知識

  • mysql で特定の日の翌日を検索する使用法は次のとおりです。DATE_ADD(yyyy-mm-dd,INTERVAL 1 DAY)

筆記試験問題69:ニウケへの各人の最終ログイン日(4)

  • 詳細説明: 各日付にログインしている新規ユーザーの数をクエリする SQL ステートメントを作成し、クエリ結果を日付の昇順に並べ替えてください。

問題解決のアイデア

  • 和+大文字小文字
  • ユーザーのログイン日に従ってグループ化し、現在のユーザーのログインが最初のログインであるかどうかを判断し、最初のログインである場合は 1 を追加します。
    • 初回ログイン:select user_id, min(date) from login group by user_id

ソースコード

select
       date,
        sum(
        case when (user_id,date) in (select user_id, min(date)from login group by user_id)
        then 1 else 0 end)
from login
group by date
order by date;

筆記試験問題70:ニウケへの各人の最終ログイン日(5)

  • 詳細説明:各日付の新規ユーザーの翌日継続率をクエリする SQL ステートメントを作成してください。結果は小数点以下 3 桁を保持し (3 桁以降は四捨五入)、クエリ結果は日付の昇順にソートされます。 。

問題解決のアイデア

  • 質問を読んだ後、質問を新しい。
  • 繰り返しになりますが、質問の要件を分割することが重要です。

ソースコード

select temp1.date, round(if(first_login = 0, 0, ifnull(retain, 0) / first_login), 3) res
from (
         -- 每天的新增用户数
         select date,
                sum(case
                        when
                                (user_id, date) in (
                                select user_id, min(date)
                                from login
                                group by user_id) then 1
                        else 0 end) first_login
         from login
         group by date
     ) temp1
    left join (
        -- 每天的留存用户数
        select date, date_sub(date, interval 1 day) new_date, count(*) retain
        from login
        where (user_id, date) in (
            select user_id, date_add(min(date), interval 1 day)
            from login
            group by user_id
        )
        group by date
    ) temp2 on temp1.date = temp2.new_date
order by date

筆記試験問題71:ニウケへの各人の最新ログイン日(6)

  • 詳細な説明: SQL ステートメントを作成して、ユーザーの名前、特定の日の時点で合格した問題の総数などのテスト情報をクエリします。クエリ結果は、最初に日付で昇順に並べ替えられ、次に名前で並べ替えられます。ログインしていて質問に回答しなかった日のデータは出力する必要はありません。

問題解決のアイデア

  • この質問に関して注意すべき点は 2 つだけです。
    • ログインしているが応答していないデータを削除する方法 ----- left join
    • 問題数の貯め方-----窓関数

ソースコード

with temp as (
    select l.user_id,l.date,number
    from login l
    left join passing_number pn on l.user_id = pn.user_id and l.date = pn.date
)
select name,date,sum(number) over(partition by name order by date) ps_num
from temp
join user on temp.user_id=user.id
where number is not null
order by date,name

筆記試験問題 72: 試験成績 (1)

  • 詳細説明: 各位置の平均スコアをクエリする SQL ステートメントを作成し、スコアを降順に並べ替えます。結果は小数点以下 3 桁が保持されます (3 桁以降は四捨五入されます)。

問題解決のアイデア

  • 質問内の各位置のスコアの平均を通じて、位置に従ってそれらをグループ化し、スコアの平均を見つけて 3 つの有効数字を保持する方法を知ることができます。round(num, 3)

ソースコード

select job, round(avg(score),3) avg_score
from grade
group by job
order by avg_score desc

筆記試験問題 73: テストの得点 (2)

  • 詳細説明: ユーザースコアがジョブ(ジョブ)の平均スコアより大きいすべての学年の属性をクエリし、IDの昇順にソートするSQL文を記述してください。

問題解決のアイデア

  • この質問を見ると、まず仕事の平均スコアを知る必要があるため、最初の質問の表を使用する必要があることがわかります。
  • 職務フィールドと成績テーブルを介して結合を実行し、平均スコアがスコアより小さいことをクエリ条件とします。

ソースコード

with temp as (
    select job, round(avg(score), 3) avg_score
    from grade
    group by job
    order by avg_score desc
)
select id, grade.job, score
from temp
         join grade on temp.job = grade.job
where temp.avg_score < grade.score
order by id;

筆記試験問題 74: テストの得点 (3)

  • 詳細な説明: 各ポジションのスコアを持つ上位 2 人のユーザーを検索してください。結果は、最初に言語名で昇順に並べ替えられ、次にポイントで降順に並べ替えられ、最後に成績 ID で昇順に並べ替えられます。

問題解決のアイデア

  • 各位置の上位 2 つのスコアについては、まずウィンドウを開いて各スコアのランキングを取得し、次にランキングが 2 以下のスコアをクエリすることを考えます。
  • 次に、2 つのテーブルを結合します

ソースコード

with temp as (    select id,           language_id,           score,           dense_rank() over (partition by language_id order by score desc) rk    from grade)select temp.id, name, scorefrom temp         left join language on temp.language_id = language.idwhere rk <= 2order by name, score desc, id;

筆記試験問題 75: テストの得点 (4)

  • 詳細説明: 各ポジションのスコアを昇順にソートし、ジョブごとに昇順にソートし、中央値の範囲を問い合わせるSQL文を記述してください。

問題解決のアイデア

  • フロア関数: 切り捨て
  • 次の解決策を覚えておいてください。これは、中央位置を見つけるための固定された記述方法です。

ソースコード

select job,    floor(( count(*) + 1 )/ 2 ) start,    floor(( count(*) + 2 )/ 2 ) endfrom gradegroup by joborder by job;

筆記試験問題 76: テストの得点 (5)

  • 問題解決のアイデア: 各ポジションのスコアの中央位置にあるすべてのグレード情報をクエリする SQL ステートメントを作成し、それを ID で昇順に並べ替えてください。

問題解決のアイデア

  • この質問を見て、まず質問の要件を分割し、最初に中央値の位置を見つけてから、対応するスコア ランキングを持つ中間テーブルと結合します。結合条件は、2 つのテーブルのジョブが同じであり、クエリ条件は中央値です。開始点がランキングと等しいか、中央値の終了点がランキングと等しいです

ソースコード

with temp as (    select job,           floor((count(*) + 1) / 2) start,           floor((count(*) + 2) / 2) end    from grade    group by job    order by job)select id, temp1.job, score, rkfrom (select id, job, score, row_number() over (partition by job order by score desc) rk      from grade) temp1         join temp on temp1.job = temp.jobwhere temp1.rk = temp.start   or temp1.rk = temp.endorder by temp1.id;

筆記試験問題77:仁受のコースオーダー分析(1)

  • 詳細な説明: ステータスが 2025 年 10 月 15 日以降に正常に購入された C++ コース、Java コース、または Python の注文をクエリする SQL ステートメントを作成し、order_info の ID に従って昇順に並べ替えてください。

問題解決のアイデア

  • クエリ条件を明確にします。購入時期が 2025 年 10 月 15 日以降であり、C++ または Java または Python が正常に購入されました。
  • 最初は書き出しませんでした。間違いは主に最後のクエリ条件にありました。オプションの問題は in を使用して解決できます。

ソースコード

select * from order_infowhere date > '2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')order by id;

筆記試験問題78:仁受のコースオーダー分析(2)

  • 詳細な説明: 2025 年 10 月 15 日以降に購入が成功したステータスで同じユーザーが 2 つ以上の注文を行った C++ コース、Java コース、または Python コースの user_id を照会する SQL ステートメントを記述してください。 user_id ソート

問題解決のアイデア

  • この質問を通じて、 > グループ化 > を持つ > 順序付けという文法順序をマスターするだけで済みます。

ソースコード

select user_idfrom order_infowhere date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')group by user_idhaving count(user_id) >= 2order by user_id

筆記試験問題79:仁受のコース順分析(3)

  • 詳細説明: 2025 年 10 月 15 日以降に同じユーザーが購入成功ステータスで 2 つ以上注文した C++ コース、Java コース、または Python コースの注文情報をクエリする SQL ステートメントを作成し、order_info に従って並べ替えてください。 IDの昇順

問題解決のアイデア

  • order by の列は group by 句に出現する列である必要があるため、サブクエリは上記に基づいてのみ使用できます。
  • datediff(date1,date2)開始時刻 date1 と終了時刻 date2 の間の日数を返します。

ソースコード

select *from order_infowhere user_id in (        select user_id        from order_info        where date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')        group by user_id        having count(*)>=2    ) and date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')order by id;

筆記試験問題80:仁受のコースオーダー分析(4)

  • 詳細説明: 2025-10-15 以降にクエリを実行する SQL ステートメントを作成してください。ユーザーが購入ステータスで 2 つ以上の C++ コース、Java コース、または Python コースを注文した場合、ユーザーの注文を出力します。user_id,前の条件 first_buy_date を満たす C++ コース、Java コース、または Python コースの最初の購入に成功した日付、C++ コース、Java コース、または Python コースの購入に成功した回数 cnt、および出力結果は user_id の昇順で並べ替えられます

問題解決のアイデア

  • この質問は非常に複雑に見えますが、上記のヒントがあれば、はるかに簡単になります。しかし、上記のヒントがない場合、この質問を分解できるでしょうか? これは SQL を書く経験でもあり、複雑すぎる質問は中間テーブルに分割されます。

ソースコード

with tmp as (    select *    from order_info    where user_id in (            select user_id            from order_info            where date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')            group by user_id            having count(*)>=2        ) and date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')    order by id)select user_id, min(date) first_buy_date, count(user_id) cntfrom tmpgroup by user_idorder by user_id;

筆記試験問題81:仁受のコースオーダー分析(5)

  • 詳細説明: 2025-10-15 以降にクエリを実行する SQL ステートメントを作成してください。ユーザーが購入ステータスで 2 つ以上の C++ コース、Java コース、または Python コースを注文した場合、ユーザーの注文を出力します。user_id,前の条件を満たす C++ コース、Java コース、または Python コースの最初の購入に成功した日付 first_buy_date、および前の条件を満たす C++ コース、Java コース、または Python コースの 2 回目の購入に成功した日付 Second_buy_date、成功した C++ コース、Java コース、または Python コースの数 cnt、および出力結果は user_id で昇順に並べ替えられます

問題解決のアイデア

  • 最初の購入と 2 回目の購入の両方を出力したい場合は、ウィンドウ関数を使用できるように、対応するランキングを知る必要があります。

ソースコード

with tmp as (    select *    from order_info    where user_id in (            select user_id            from order_info            where date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')            group by user_id            having count(*)>=2        ) and date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')    order by id)select user_id, min(date), max(date), cntfrom(    select user_id, date, row_number() over (partition by user_id order by date) rk,       count(user_id) over(partition by user_id) cntfrom tmp        )tmp2where rk<=2group by user_id, cntorder by user_id;

筆記試験問題82:仁受のコースオーダー分析⑥

  • 詳細な説明: 同じユーザーが 2025 年 10 月 15 日以降に 2 回注文し、購入ステータスが正常である 3 回以上の注文を行った C++ コース、Java コース、または Python コースの注文 ID をクエリする SQL ステートメントを作成してください。グループに参加する場合とクライアント名の情報 最後の列が非グループオーダーの場合は対応するクライアント名が表示されます グループオーダーの場合はNULLが表示され、order_infoは昇順にソートされます。

問題解決のアイデア

  • 質問の要件に従って返されたフィールドによると、2 つのテーブルを結合する必要があることがわかります。質問では、グループ注文の場合は NULL が表示されると書かれているため、使用します。订单表 left join 客户端表

ソースコード

with tmp as (    select *    from order_info    where user_id in (            select user_id            from order_info            where date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')            group by user_id            having count(*)>=2        ) and date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')    order by id)select tmp.id,is_group_buy,namefrom tmpleft join client on tmp.client_id = client.idorder by id;

筆記試験問題83:仁受のコースオーダー分析(7)

  • 詳細説明: 2025 年 10 月 15 日以降に同じユーザーによって正常に購入された C++ コース、Java コース、または Python コースのソース情報を照会する SQL ステートメントを作成してください。最初の列に表示されるのはクライアント名です。これはグループ注文です。GroupBuy が表示されます。2 番目の列には、このクライアント (またはグループ注文) の注文数が表示されます。最終結果は、最初の列 (ソース) によって昇順で並べ替えられます。

問題解決のアイデア

  • if ステートメントを使用して null を置き換えるだけです
  • これは別の関数ですIFNULL(expression, alt_value)。最初のパラメータの式が NULL の場合、2 番目のパラメータが返されます。

ソースコード

with tmp as (    select *    from order_info    where user_id in (            select user_id            from order_info            where date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')            group by user_id            having count(*)>=2        ) and date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')    order by id)select name_n,count(*)from (    select if(is_group_buy='Yes','GroupBuy',name) name_n    from tmp    left join client on tmp.client_id = client.id)tmp1group by name_norder by name_n;

筆記試験問題84:インターンシップスクエアでの履歴書提出分析(1)

  • 詳細説明: 2025 年に提出された履歴書の役職と数をクエリし、数量の降順に並べ替える SQL ステートメントを作成してください。

問題解決のアイデア

  • 重要なのは 2025 年をどう判断するかですが、ステートメントや関数など、さまざまな方法があります。date_format(date,"%Y")
  • 式をsumで渡す方法を採用しています。

ソースコード

select    job,sum(if(year(date)=2025,num,0)) cntfrom resume_infogroup by joborder by cnt desc

筆記試験問題85:インターンシップスクエアでの履歴書提出分析(2)

  • 詳細な説明: 2025 年に履歴書を提出するポジションごとに、各月に受け取った履歴書の数をクエリする SQL ステートメントを作成し、最初に月ごとに降順に並べ替え、次に履歴書の数によって降順に並べ替えてください。

問題解決のアイデア

  • それを理解するとはどういう意味ですか每一个月每个岗位收到简历的数量これが役職と月ごとにグループ化されていることがわかり、履歴書の数を集計できます。

ソースコード

select    job,date_format(date,"%Y-%m") month,sum(num) cntfrom resume_infowhere year(date) = 2025group by job,monthorder by month desc, cnt desc 

筆記試験問題86:インターンシップスクエアでの履歴書提出分析(3)

  • 詳細な説明: 2025 年に履歴書が提出された各ポジション、各月に受け取った履歴書の数、および 2026 年の同じ月に同じポジションで受け取った対応する履歴書の数をクエリする SQL ステートメントを作成してください。結果は、まず first_year_mon の降順に並べ替えられ、次にジョブごとに降順に表示されます。

問題解決のアイデア

  • 前の 2 つの質問の伏線に基づいて、2025 年に各ポジションごとに受け取った履歴書の数を簡単に取得することができ、2026 年も同様になるでしょう。したがって、最初に 2 つのクエリ (1 つは 2025 用、もう 1 つは 2026 用) を作成し、最後にそれらを結合できます。まず第一に、位置が同じである必要があり、第二に、同じ月にある必要があります (問題にはこう書かれています同一个月同岗位); 問題を注意深く読めば、簡単に解けます。

ソースコード

select tmp1.job,       first_year_mon,       first_year_cnt,       second_year_mon,       second_year_cntfrom (         select job,                date_format(date, "%Y-%m") first_year_mon,                sum(num)                   first_year_cnt         from resume_info         where year(date) = 2025         group by job, first_year_mon     ) tmp1         join (    select job,           date_format(date, "%Y-%m") second_year_mon,           sum(num)                   second_year_cnt    from resume_info    where year(date) = 2026    group by job, second_year_mon) tmp2 on tmp1.job = tmp2.job and right(first_year_mon, 2) = right(second_year_mon, 2)order by first_year_mon desc, job desc

筆記試験問題87:最悪のポジションは何ですか(1)

  • 詳細説明: SQL クエリを作成してください。学生が自分の総合スコアを知っている場合、最悪の順位は何ですか? 結果は成績の昇順で並べ替えられます。

問題解決のアイデア

  • 問題は成績の高い順にソートする必要がありますが、総合スコアが高いほどグレードが高いため、実際には総合スコアの昇順にソートされます。
  • 2 行目のスコアは、最初の行に元の 2 行目を加えたものに等しくなります。ウィンドウを開くだけです。

ソースコード

select grade, sum(number) over(order by grade)from class_grade;

筆記試験問題88:最悪のポジションは何ですか(2)

  • 詳細説明: 教師は、生徒の総合スコアの中央値を知りたいと考えています。クエリを支援する SQL を作成してください。中央値が 1 つだけの場合は、1 を出力します。中央値が 2 つある場合は、成績で昇順に並べ替えます。出力

問題解決のアイデア

  • この点は問題の解決に使用されます。特定の数値の累積的な正負のシーケンスがシーケンス全体の数値の数の半分より大きい場合、それが中央値になります。
  • 上記の結論が分かれば、正系列の累積はすでに得られているので、逆系列の累積に desc を追加するだけです。

ソースコード

select gradefrom (         select grade,                #(select sum(number) from class_grade) as total,    			sum(number) over() total,                sum(number) over (order by grade)        a,                sum(number) over (order by grade desc)   b         from class_grade     ) tmpwhere a >= total / 2  and b >= total / 2order by grade

コードには学習する価値のあるものがあります。集計関数は非集計フィールドと一緒に配置できないため、select ステートメントを select に置くことができます。そのため、集計値をクエリするために select を書き換えます。

筆記試験問題89:最も得点が多かった人(1)

  • 詳細な説明: SQL を作成して、最もスコアが増加したユーザーの名前とその合計スコアを調べてください (この質問のデータにより、最も高いスコアを持つユーザーは 1 人だけであることが保証されます)

問題解決のアイデア

  • 最も多くのポイントを獲得したユーザーを見つけるには、まずそのユーザーが追加したすべてのポイントを合計する必要があります。グループ累計

ソースコード

select name, cntfrom (         select user_id, sum(grade_num) cnt         from grade_info         group by user_id         order by cnt desc         limit 1     ) tmp         join user on tmp.user_id = user.id;

筆記試験問題90:最も得点が多かった人(2)

  • 詳細説明:最もポイントが増えたユーザーのID(複数可)、名前、合計ポイントを調べるSQLを記述してください クエリ結果はIDの昇順にソートされます。

問題解決のアイデア

  • 中間テーブルがクエリ内で 2 回以上使用される場合、with 中间表名 as (select 子句)一時テーブルを作成できます。

ソースコード

with tmp_table as (    select user_id, sum(grade_num) cnt    from grade_info    group by user_id    order by cnt desc)select user_id, name, cntfrom tmp_tablejoin user on user.id = tmp_table.user_idwhere cnt = (    select max(cnt) max_cnt    from tmp_table)

筆記試験問題91:最も得点が多かった人(3)

  • 詳細説明: 最もポイントの高いユーザーのID、名前、合計ポイント(複数の場合もあります)を調べるSQLを記述してください。クエリ結果はIDの昇順にソートされます。

問題解決のアイデア

  • 上記の考え方で、この問題で解決する必要がある唯一の問題は、type="reduce" の場合、積分を加算するのではなく減算する必要があることです。

ソースコード

with tmp_table as (    select user_id, sum(grade_num) cnt    from (select user_id, if(type = "reduce", -grade_num, grade_num) grade_num from grade_info) tmp1    group by user_id)select id, name, cntfrom tmp_table         join user on tmp_table.user_id = user.idwhere cnt = (    select max(cnt)    from tmp_table)order by id

おすすめ

転載: blog.csdn.net/qq_42397330/article/details/118719127