Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 高级SQL选择查询_Mysql_Sql_Select_Join - Fatal编程技术网

Mysql 高级SQL选择查询

Mysql 高级SQL选择查询,mysql,sql,select,join,Mysql,Sql,Select,Join,此表表示某个人在特定的一周访问某个网站。每个cookie代表一个人。每个条目代表在特定的一周内访问此站点的人。例如,最后一个条目表示“d”在第3周到达该站点 我想知道在接下来的一周里,有多少(相同的)人会继续回来,如果给他们一个开始的一周时间来观察的话。 例如,如果我看第一周。我将得到如下结果: week cookie 1 a 1 b 1 c 1 d 2 a 2 b 3 a

此表表示某个人在特定的一周访问某个网站。每个cookie代表一个人。每个条目代表在特定的一周内访问此站点的人。例如,最后一个条目表示“d”在第3周到达该站点

我想知道在接下来的一周里,有多少(相同的)人会继续回来,如果给他们一个开始的一周时间来观察的话。

例如,如果我看第一周。我将得到如下结果:

week      cookie
1         a
1         b
1         c
1         d
2         a 
2         b
3         a
3         c
3         d
因为第1周有4个用户。第二周,他们中只有两人(a,b)回来了。在这三个星期里,只有1(a)人来了


如何执行select查询以找到答案?这张表会很大:可能有100周,所以我想找到正确的方法。

好吧,假设您的表名为
visions
,您对周数
n
感兴趣。您想知道,对于每个星期编号
w>=n
,哪些用户出现在每个这样的星期
w

那么有多少个这样的星期

1 | 4
2 | 2
3 | 1
每个用户访问了多少周

select count(*)
from visits
where week >= n;
假设您有第1、3、4、5、6、7、9、10和13周,并且您对第5周感兴趣。上面的第一个查询给出了6个星期,因为有6个星期的兴趣:5、6、7、9、10和13。第二个查询将为每个用户提供他们在过去几周中访问的次数。现在,您想知道其中有多少用户的计数是6

我认为这是可行的:

select user, count(user)
from visit
group by user
where week >= n;
但是我现在没有访问MySQL的权限。如果它不起作用,那么也许这种方法是有意义的,并为您指明了正确的方向。编辑:我明天可以测试。

使用自连接:

select user, count(user)
from visit
group by user
having count(user) = (
    select count(*)
    from visits
    where week >= n)
where week >= n;
这将为您提供第二次和以后的访问记录


但我认为更好的方法是,只需按cookie分组,这样就可以得到每个cookie的访问次数;任何大于1的数字都是返回用户。

这是我的解决方案,并不简单,但正如我所测试的,它确实解决了您的问题:

首先,我们声明一个存储过程,它将在特定的一周内为访问者提供字符串分隔,如果您愿意,可以使用group_concat,但我是这样做的-考虑到group_concat有一个文本限制

SELECT ... FROM visits AS v1 LEFT JOIN visits AS v2 ON v2.week = v1.week+1
WHERE v2.week IS NOT NULL
GROUP BY cookie
然后我们声明一个函数来包装该存储过程,这样我们就可以方便地在查询内部调用:

DELIMITER $$

DROP PROCEDURE IF EXISTS `db`.`get_visitors_for_week`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `get_visitors_for_week`(id_week INTEGER, OUT result TEXT)
BEGIN
    DECLARE should_continue INT DEFAULT 0;
    DECLARE c_cookie CHAR(1);
    DECLARE r CURSOR FOR SELECT v.cookie
                FROM visits v WHERE v.week = id_week;
    DECLARE CONTINUE HANDLER FOR NOT FOUND
        SET should_continue = 1;
    OPEN r;
    REPEAT
        SET c_cookie = NULL;
        FETCH r INTO c_cookie;
        IF c_cookie IS NOT NULL THEN
            IF result IS NULL OR result = '' THEN
                SET result = c_cookie;
            ELSE SET result = CONCAT(result,',',c_cookie);
            END IF;
        END IF;
        UNTIL should_continue = 1
    END REPEAT;
    CLOSE r;
    END$$

DELIMITER ;
然后我们必须统计本周和上周的访客数量——当然是每周的访客数量——我们通过在串联列表中搜索cookie字符串来“看到”。这是最后一个查询:

DELIMITER $$

DROP FUNCTION IF EXISTS `db`.`concat_values`$$

CREATE DEFINER=`root`@`localhost` FUNCTION `concat_values`(id_week INTEGER) RETURNS TEXT CHARSET latin1
BEGIN
    DECLARE result TEXT;
    CALL get_visitors_for_week(id_week, result);
    RETURN result;
    END$$

DELIMITER ;

将条件
v.week>=1
-1-替换为要开始的周数。

此查询使用变量跟踪相邻周,并确定它们是否连续:

SELECT
  v.week,
  SUM(IF(IFNULL(concat_values(v.week - 1)) OR INSTR(concat_values(v.week - 1),v.cookie) > 0, 1, 0)) AS Visitors
FROM (SELECT
        v.week,
        v.cookie,
        vt.visitors
      FROM visits v
        INNER JOIN (SELECT DISTINCT
                      v.week,
                      concat_values(v.week) AS visitors
                    FROM visits v) AS vt
          ON v.week = vt.week) AS v
WHERE v.week >= 1
GROUP BY v.week
上述查询的输出,其中周>=1:

create table webhist(week int, cookie char);
insert into webhist values (1, 'a'), (1, 'b'), (1, 'c'), (1, 'd'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'c'), (3, 'd');
上述查询的输出,其中周>=2:

+--------------+----------+
| conseq_weeks | count(*) |
+--------------+----------+
|            1 |        4 |
|            2 |        2 |
|            3 |        1 |
+--------------+----------+

p、 这是一个很好的问题,但有点像一个破坏者。由于某些原因,这些答案大多过于复杂,不需要游标或循环之类的东西

我想知道到底有多少(同样的)人继续回到美国 接下来的一周,当有一周的开始时间时

如果您想知道一周内访问过多少用户,以及以后每周访问过多少用户,请执行以下操作:

+--------------+----------+
| conseq_weeks | count(*) |
+--------------+----------+
|            1 |        2 |
|            2 |        1 |
+--------------+----------+
但是,如果您在第一周有10个用户,然后在接下来的5周内访问了5个不同的用户,您将继续看到1=10,2=5,3=5,4=5,5=5,6=5,依此类推,那么这不会显示结果随时间而递减,相反,您希望看到5=x,其中x是连续5周每周访问的用户数。为此,请参见以下内容:

SELECT visits.week, COUNT(1) AS [NumRepeatUsers]
FROM visits 
WHERE EXISTS (
    SELECT TOP 1 1 
    FROM visits AS nextWeek 
    WHERE nextWeek.week = visits.week+1 
      AND nextWeek.cookie = visits.cookie
  )
  AND EXISTS (
    SELECT TOP 1 1 
    FROM visits AS searchWeek
    WHERE searchWeek.week = @week 
      AND nextWeek.cookie = visits.cookie
  )
GROUP BY visits.week
ORDER BY visits.week

这将给你1=10,2=5,3=4,4=3,5=2,6=1或类似的结果,这是一个有趣的例子

我试图找出每个人访问的最后一周是什么时候。
这被计算为开始当天或之后的第一周,其中下一周没有访问

一旦你知道了每个用户的最后访问周,你只需统计每个星期的最终访问是在该周或之后的不同用户的数量

SELECT visits.week, COUNT(1) AS [NumRepeatUsers]
FROM visits 
WHERE EXISTS (
    SELECT TOP 1 1 
    FROM visits AS nextWeek 
    WHERE nextWeek.week = visits.week+1 
      AND nextWeek.cookie = visits.cookie
  )
  AND EXISTS (
    SELECT TOP 1 1 
    FROM visits AS searchWeek
    WHERE searchWeek.week = @week 
      AND nextWeek.cookie = visits.cookie
  )
  AND visits.week - @week = (
    SELECT COUNT(1) AS [Count]
    FROM visits AS searchWeek
    WHERE searchWeek.week BETWEEN @week+1 AND visits.week
      AND nextWeek.cookie = visits.cookie
  )
GROUP BY visits.week
ORDER BY visits.week
编辑
-谢谢你的关注。在“fv”查询中,我也丢失了分组。哎呀。
-我已删除了表示参数的注释。
-我已删除不必要的文件。
再次编辑
-在第一周添加了额外的内容,因为它无法处理从第2周开始的问题

当我运行此操作时(必须承认是在MS Access上)

从第一周开始,我得到:

SELECT wks.week, COUNT(cookie) as Visitors
FROM (SELECT a.cookie, MIN(a.week) AS FinalVisit
      FROM WeekVisits a 
           INNER JOIN WeekVisits FirstWeek
           ON a.cookie = FirstWeek.cookie
      WHERE a.week >= 1
        AND FirstWeek.week = 1
        AND NOT EXISTS (SELECT 1 
                        FROM WeekVisits b
                        WHERE b.week = a.week + 1
                          AND b.cookie = a.cookie)
      GROUP BY a.cookie) fv
     INNER JOIN
     (SELECT DISTINCT week 
      FROM WeekVisits
      WHERE week >= 1) wks
     ON fv.FinalVisit >= wks.week 
GROUP BY wks.week
ORDER BY wks.week
+------+----------+ |周|访客| | 1 | 4 | | 2 | 2 | | 3 | 1 | +------+----------+ 从第2周开始,我得到:

+------+----------+ | week | Visitors | | 1 | 4 | | 2 | 2 | | 3 | 1 | +------+----------+ +------+----------+ |周|访客| | 2 | 2 | | 3 | 1 | +------+----------+ 。。如预期。
(要从第2周开始,您需要在与“周”列比较的三个位置将1更改为2)

该方法看起来很合理,但MySQL的语法可能需要调整。

对不起,这对你们来说可能并不难,但我无法理解。非常感谢你们的帮助!!实际上这是一个有趣的问题。那么你的意思是给定一个周号
n
,那么对于每个周号
w>n
,给出所有周
n
w
的访问用户数?或者至少只在
n
w
访问?我指的是整个星期。例如,我想在第三周后的10周内检查。The variable of the query will just be 3 and 10.  Thanks. please help.不客气,但这次很难。不要因为你被卡住而感到难过。在SQL中,“为所有人”是很难的。我正在做某事。。。。thank you so much.  but i still cannot get i +------+----------+ | week | Visitors | | 1 | 4 | | 2 | 2 | | 3 | 1 | +------+----------+ +------+----------+ | week | Visitors | | 2 | 2 | | 3 | 1 | +------+----------+