5

私は、5人の最も近いユーザーを次の誕生日でソートした結果セットをソートしようとしています。これは、うるう年が始まるまで完全に機能します。例えば:

  • 5月15日-残り96日
  • 5月15日-残り97日

上の結果は1987年の出生で、下の結果は1988年の出生です。u_birthはyyyy-mm-ddとして保存されます。クエリ全体を書き直すことなく、この問題を分類する簡単な方法はありますか?

SELECT u_birth, IF( DAYOFYEAR( u_birth ) >= DAYOFYEAR( NOW() ), 
          DAYOFYEAR( u_birth ) - DAYOFYEAR( NOW() ), 
          DAYOFYEAR( u_birth ) - DAYOFYEAR( NOW() ) +  
      DAYOFYEAR( CONCAT( YEAR( NOW() ), '-12-31' ) ) 
 )  
 AS distance
FROM (blog_users)
WHERE `s_agehide` = 0
ORDER BY distance ASC
LIMIT 5

このクエリは、mysqlのマニュアルから取得および変更されています:http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#c7489

4

4 に答える 4

8

アルゴリズムがその人の生年に依存している場合は、明らかに問題があります。これを回避するには、まず現在の日付の後の各人の次の誕生日を見つけ、次にその日付と現在の差を計算します。

SELECT u_birth, DATEDIFF(next_birthday, NOW()) AS distance FROM (
    SELECT *, ADDDATE(birthday, INTERVAL birthday < DATE(NOW()) YEAR) AS next_birthday
    FROM (
        SELECT *, ADDDATE(u_birth, INTERVAL YEAR(NOW()) - YEAR(u_birth) YEAR) AS birthday
        FROM blog_users
        WHERE s_agehide = 0
    ) AS T1
) AS T2
ORDER BY distance ASC
LIMIT 5

結果:

'1992-02-29', 20
'1993-03-01', 21
'1987-05-15', 96
'1988-05-15', 96
'1988-09-18', 222

テストデータ:

CREATE TABLE blog_users (u_birth NVARCHAR(100) NOT NULL, s_agehide INT NOT NULL);
INSERT INTO blog_users (u_birth, s_agehide) VALUES
('1987-05-15', 0),
('1988-05-15', 0),
('1988-09-20', 0),
('2000-01-02', 0),
('2000-01-03', 1),
('1988-09-19', 0),
('1988-09-18', 0),
('1992-02-29', 0),
('1993-03-01', 0);

うるう日に生まれた人は、うるう年以外の年に2月28日の誕生日を迎えると想定されていることに注意してください。

また、クエリにはユーザーのユーザーIDが含まれていません。おそらくこれも追加したいと思うでしょう。

于 2010-02-08T20:14:01.467 に答える
2
SELECT
    CONCAT(
        YEAR(CURRENT_DATE()),
        '-',
        DATE_FORMAT((birthDate),
            '%m-%d'
        )
    ),
    fullName
FROM
    employees
WHERE
    birthDate != 0
AND(
    CONCAT(
        YEAR(CURRENT_DATE())+ 1,
        '-',
        DATE_FORMAT((birthDate),
            '%m-%d'
        )
    )BETWEEN CURRENT_DATE()
    AND DATE_ADD(
        CURRENT_DATE(),
        INTERVAL 21 DAY
    )
    OR CONCAT(
        YEAR(CURRENT_DATE()),
        '-',
        DATE_FORMAT((birthDate),
            '%m-%d'
        )
    )BETWEEN CURRENT_DATE()
    AND DATE_ADD(
        CURRENT_DATE(),
        INTERVAL 21 DAY
    )
)

ps:birthDateは、従業員の生年月日を保存した列です。 従業員はテーブル名です。

于 2011-08-27T15:27:35.360 に答える
1

dayofyearうるう年の2月29日以降は、通常より1日先に使用しないでください。代わりに、月と日を抽出し、それらを今日の年と連結します。次に、比較を行います。

そのようです:

SELECT u_birth, 
  IF(DATE(CONCAT(YEAR(NOW()),'-',MONTH(u_birth),'-',DAY(u-birth))) >= DATE(NOW()),
...

ETA:

生年月日を誕生日に変換する式を書き直す必要がないように、変数に固定します。クエリで直接使用できるように、変換を行う関数を作成することをお勧めします。

SET @birthday= SELECT DATE(CONCAT(YEAR(NOW()),'-',MONTH(u_birth),'-',DAY(u-birth))) FROM users WHERE user_id=x; //obviously only good for one value, but use the example for the calculation

SELECT u_birth, 
       IF(DATE(@birthday)>=DATE(NOW()), 
          DATEDIFF(DATE_ADD(@birthday, INTERVAL 1 YEAR),NOW()), 
          DATEDIFF(NOW(),@birthday)
       ) as days
FROM users WHERE user_id=x;
于 2010-02-08T20:02:41.730 に答える
1

たぶん誰かがこのコードの平和に触発されるでしょう。

私の場合は完璧に機能しましたが、日付の計算はたくさんあると思います...

SELECT CONCAT(YEAR(CURRENT_DATE()),'-',DATE_FORMAT( FROM_UNIXTIME(date_of_birth), '%m-%d' )), fe_users.* 
FROM `fe_users`
WHERE `date_of_birth` != 0 AND (
     CONCAT(YEAR(CURRENT_DATE())+1,'-',DATE_FORMAT( FROM_UNIXTIME(date_of_birth), '%m-%d' )) BETWEEN CURRENT_DATE() AND DATE_ADD(CURRENT_DATE(), INTERVAL 7 DAY)
     OR
     CONCAT(YEAR(CURRENT_DATE()),'-',DATE_FORMAT( FROM_UNIXTIME(date_of_birth), '%m-%d' )) BETWEEN CURRENT_DATE() AND DATE_ADD(CURRENT_DATE(), INTERVAL 7 DAY)
)

このSQLコードの平和により、date_of_birth(unix-timestampとして保存)が7日以内になるテーブルfe_usersのすべてのユーザーを取得できます。date_add()関数で使用される間隔を変更することで、これを21日に簡単に延長できます。

于 2011-02-09T01:15:37.407 に答える