Как бы я сделал это присоединиться к этой статистике? - PullRequest
2 голосов
/ 24 января 2012

Во-первых, извините за заголовок вопроса. Я не в курсе статистики или подобного рода трудностей с присоединением, что бы это ни было.

У меня есть запрос *, с его помощью я по сути генерирую три вещи: random_sex, random_first и random_last. Я пытаюсь присоединиться сейчас с этим методом .

 random_sex |   random_first   |   random_last    
------------+------------------+------------------
 male       | 47.7101715711225 | 24.3833348881337
 male       | 72.8463141907472 | 28.3560050522089
 female     | 72.8617294209544 | 33.3203859277759
 male       | 39.3406164890062 | 26.3352867371729
 female     | 28.6855500966031 | 65.8870893270099
 female     | 35.5960198949557 | 83.1188118207422
 male       | 11.5711074977927 |  10.544433838184
 male       | 15.6900786811765 | 18.7324617852545
 male       | 24.9860797089245 | 8.98265511383023
 female     | 80.4563122882508 |  35.594445341751
(10 rows)

По существу данные переписи располагаются в такой таблице ...

    name    | freq  | cumfreq | rank | name_type 
------------+-------+---------+------+-----------
 SMITH      | 1.006 |   1.006 |    1 | LAST
 JOHNSON    |  0.81 |   1.816 |    2 | LAST
 WILLIAMS   | 0.699 |   2.515 |    3 | LAST
 JONES      | 0.621 |   3.136 |    4 | LAST
 BROWN      | 0.621 |   3.757 |    5 | LAST
 DAVIS      |  0.48 |   4.237 |    6 | LAST
 MILLER     | 0.424 |    4.66 |    7 | LAST
 WILSON     | 0.339 |       5 |    8 | LAST
 MOORE      | 0.312 |   5.312 |    9 | LAST
 TAYLOR     | 0.311 |   5.623 |   10 | LAST
 ANDERSON   | 0.311 |   5.934 |   11 | LAST
 THOMAS     | 0.311 |   6.245 |   12 | LAST
 JACKSON    |  0.31 |   6.554 |   13 | LAST
 WHITE      | 0.279 |   6.834 |   14 | LAST
 HARRIS     | 0.275 |   7.109 |   15 | LAST
 MARTIN     | 0.273 |   7.382 |   16 | LAST
 THOMPSON   | 0.269 |   7.651 |   17 | LAST
 GARCIA     | 0.254 |   7.905 |   18 | LAST
 MARTINEZ   | 0.234 |    8.14 |   19 | LAST

И в этом случае ..

 random_sex |   random_first   |    random_last    
 male       | 47.7101715711225 | 24.3833348881337

Я хочу, чтобы это было соединено вот так (процедурно):

=# select * from census.names where cumfreq > 47.7101715711225 AND name_type = 'MALE_FIRST' order by cumfreq asc limit 1;
  name  | freq  | cumfreq | rank | name_type  
--------+-------+---------+------+------------
 SILVER | 0.009 |  47.717 | 1424 | MALE_FIRST

=# select * from census.names where cumfreq > 24.3833348881337 AND name_type = 'LAST' order by cumfreq asc limit 1;
  name  | freq  | cumfreq | rank | name_type 
--------+-------+---------+------+-----------
 HARPER | 0.054 |  24.408 |  185 | LAST

Так что это мужское имя будет Серебряный Харпер. Я никогда не встречал никого в своей жизни, но они существуют.

Я бы хотел вернуть «Серебряный» «Арфист» в приведенном выше запросе, а не случайные числа. Как я могу заставить это работать так?


СНОСКА

*: Просто, чтобы было проще:

SELECT
   CASE WHEN RANDOM() > 0.5 THEN 'male' ELSE 'female' END AS random_sex
   , RANDOM() * 90.020 AS random_first -- dataset is 90% of most popular
   , RANDOM() * 90.483 AS random_last
FROM generate_series(1,10,1);

Ответы [ 4 ]

2 голосов
/ 24 января 2012

Я на самом деле не знаю и о статистике.но я думаю, что это то, что вы хотите

Давайте назовем таблицу, которая возвращает случайные столбцы Randoms

WITH RANDOMS AS
(
   SELECT
   CASE WHEN RANDOM() > 0.5 THEN 'male' ELSE 'female' END AS random_sex
   , RANDOM() * 90.020 AS random_first 
   , RANDOM() * 90.483 AS random_last
   FROM generate_series(1,10,1)
)
SELECT (
        SELECT A.NAME 
        FROM census.names A
        WHERE A.cumfreq > R.random_first
        AND A.name_type = 'MALE_FIRST'
        order by A.cumfreq asc limit 1
       ), 
       (
        SELECT A.NAME 
        FROM census.names A
        WHERE A.cumfreq > R.random_last
        AND A.name_type = 'LAST'
        order by A.cumfreq asc limit 1
       ) AS NAME
FROM RANDOMS R ;
0 голосов
/ 24 января 2012
EXPLAIN ANALYZE SELECT
  r.sex
  , r.detail
  , COALESCE(
    (SELECT name FROM census.names AS mf WHERE r.sex = 'male' AND mf.name_type = 'MALE_FIRST' AND mf.cumfreq > r.first ORDER BY cumfreq LIMIT 1)
    , (SELECT name FROM census.names AS ff WHERE r.sex = 'female' AND ff.name_type = 'FEMALE_FIRST' AND ff.cumfreq > r.first ORDER BY cumfreq LIMIT 1)
  ) AS first
  , (SELECT name FROM census.names AS l WHERE l.name_type = 'LAST' AND l.cumfreq > r.last ORDER BY cumfreq LIMIT 1) AS last
FROM (
  SELECT
    RANDOM() * 90.020 AS first
    , RANDOM() * 90.483 AS last
    , CASE WHEN RANDOM() > 0.5 THEN 'male' ELSE 'female' END AS sex
  FROM generate_series(1,10,1)
) AS r;

Это на самом деле то, чем я закончил.

0 голосов
/ 24 января 2012

Коррелированные подзапросы?

SELECT
  *
FROM
  yourRandomTable
INNER JOIN
  census.names         AS first_name
    ON  first_name.cumfreq = (SELECT MIN(cumfreq)
                              FROM   census.names
                              WHERE  cumfreq > yourRandomTable.random_first
                                AND  type    = yourRandomTable.random_sex + '_FIRST')
    AND first_name.type    = yourRandomTable.random_sex + '_FIRST'
INNER JOIN
  census.names         AS last_name
    ON  last_name.cumfreq  = (SELECT MIN(cumfreq)
                              FROM   census.names
                              WHERE  cumfreq > yourRandomTable.random_last
                                AND  type    = 'LAST')
    AND last_name.type     = 'LAST'

Вы можете варьировать этот шаблон довольно сильно.Как именно вы решите это сделать, зависит от того, как вы настроили свои индексы.

0 голосов
/ 24 января 2012

Чит, декартово произведение

Select q1.Name as Forename, q2.Name as Surname
From 
(select Name from census.names where cumfreq > 47.7101715711225 
 AND name_type = 'MALE_FIRST' order by cumfreq asc limit 1) q1, 
(select Name from census.names where cumfreq > 24.3833348881337 
 AND name_type = 'LAST' order by cumfreq asc limit 1) q2
...