【问题标题】:Pulling information from 2 sources and counting从 2 个来源提取信息并计数
【发布时间】:2015-01-06 20:27:15
【问题描述】:

有人要求我在工作中创建一个系统,用于记录通过我们的 VoIP 系统拨打和接听的电话数量。如果我能够更改数据源的结构,我可能会这样做,但在这种情况下,我不允许更改它,这现在取决于我询问比我更专业的人。

数据源 1(使用 MSSQL)- 这会记录登录到我们内部网的用户以及他们的扩展名:

+-------+----------------+--------------+---------------------+
| ID    | USERNAME       | EXTENSION    | LOGGEDIN            |
+-------+----------------+--------------+---------------------+
| 1     | JESS           | 101          | 2014-11-10 12:00:00 |
+-------+----------------+--------------+---------------------+
| 2     | SARAH          | 203          | 2014-11-10 12:21:00 |
+-------+----------------+--------------+---------------------+
| 3     | FERN           | 124          | 2014-11-10 12:21:31 |
+-------+----------------+--------------+---------------------+
| 4     | SARAH          | 101          | 2014-11-10 13:12:00 |
+-------+----------------+--------------+---------------------+

数据源 2(使用 MySQL)- 数据源 2 包含使用 VoIP 系统拨打和接听的所有电话

+-------+----------------+---------------+---------------------+
| ID    | SRC            | DST           | TIME                |
+-------+----------------+---------------+---------------------+
| 1     | 101            | 02035654684   | 2014-11-10 12:01:00 |
+-------+----------------+---------------+---------------------+
| 2     | 203            | 02087816328   | 2014-11-10 12:22:00 |
+-------+----------------+---------------+---------------------+
| 3     | 124            | 02078939273   | 2014-11-10 12:23:31 |
+-------+----------------+---------------+---------------------+
| 4     | 101            | 04672738782   | 2014-11-10 13:15:00 |
+-------+----------------+---------------+---------------------+
| 5     | 07863522413    | 101           | 2014-11-10 13:21:00 |
+-------+----------------+---------------+---------------------+
| 6     | 02076352423    | 203           | 2014-11-10 13:25:31 |
+-------+----------------+---------------+---------------------+
| 7     | 07836325726    | 101           | 2014-11-10 13:56:00 |
+-------+----------------+---------------+---------------------+

这是我希望能够打印的内容:

+-------+----------------+--------------+--------------+-------------+
| ID    | USERNAME       | INCOMING     | OUTGOING     | TOTAL       |
+-------+----------------+--------------+--------------+-------------+
| 1     | JESS           | 0            | 1            | 1           |
+-------+----------------+--------------+--------------+-------------+
| 2     | SARAH          | 2            | 2            | 4           |
+-------+----------------+--------------+--------------+-------------+
| 3     | FERN           | 0            | 1            | 1           |
+-------+----------------+--------------+--------------+-------------+

从上表中可以看出,Sarah 从分机 203 开始​​,然后在 Jess 离开后登录到 101。她在 203 登录时拨打了 1 个电话,在 101 登录时拨打了 1 个电话。她在分机 101 登录时接听了 2 个电话。

我将在这个项目中使用 PHP。理想情况下,我想按总降序对上面的表格进行排序,但我相信一旦我有了构建块,我可以自己解决这个问题。

提前感谢您对此提供的任何帮助。

注意:我考虑过创建一个临时表来提取信息,但我已经被告知这是一个坏主意,因为查询的执行时间以及我需要提取信息的频率。该脚本将每 10 秒运行一次,因此我使用的任何查询都需要非常精简。

【问题讨论】:

  • 您遇到了哪些问题?你走了多远?
  • 我建议设置一个从ms sql到mysql的链接服务器,并编写一个组装数据的存储过程。
  • @TabAlleman 我还没有写任何 SQL 语句,因为我不太清楚如何解决这个问题,所以我在这里。
  • @DanBracuk 这是一个可行的选择,但我不知道这是否会给我实时信息。我想我可以每隔几秒轮询一次数据库。
  • 正如@DanBracuk 所说,使用 MSSQL Server 中的链接服务器连接到您的 MySQL 数据库。然后使用存储过程(如建议的那样)或视图来定义您在 php 中想要的布局或您最终使用的任何前端。链接服务器实时获取数据,因此不需要“轮询数据库”。我假设您正在尝试创建某种性能仪表板。如果您配置了 SQL Server Reporting Services 实例,我会在其中编写报告,您可以自动设置刷新数据的频率。

标签: php mysql sql sql-server database


【解决方案1】:
SELECT
   u.ID,
   u.USERNAME,
   coalesce(tSRC.INCOMING,0) as INCOMING,
   coalesce(tDST.OUTGOING,0) as OUTGOING,
   (coalesce(tSRC.INCOMING,0)+coalesce(tDST.OUTGOING,0)) as total
FROM
table1 u
LEFT JOIN (
   SELECT a.SRC as ext , count(a.ID) as INCOMING
   FROM table2 a WHERE CHAR_LENGTH(a.SRC)=3 GROUP BY a.SRC
   ) tSRC ON tSRC.ext = u.EXTENSION
LEFT JOIN (
   SELECT b.SRC as ext , count(b.ID) as OUTGOING
   FROM table2 b WHERE CHAR_LENGTH(b.DST)=3 GROUP BY b.DST
   ) tDST ON tDST.ext = u.EXTENSION

编辑:更好的版本:

SELECT
   u.ID,
   u.USERNAME,
   u.EXTENSION,
   COUNT(distinct a.ID) as INCOMING,
   COUNT(distinct b.ID) as OUTGOING,
   (COUNT(distinct a.ID)+COUNT(distinct b.ID)) as TOTAL
FROM
table1 u
LEFT JOIN table2 a ON u.EXTENSION=a.SRC
LEFT JOIN table2 b ON u.EXTENSION=b.DST
GROUP BY u.EXTENSION 

【讨论】:

  • 谢谢大卫,我相信如果表在同一个数据库中,这会起作用,但它们不是:(它们在使用 2 个不同引擎的 2 个不同数据库中(数据存储 1 是 MSSQL,数据存储 2是 MySQL)。你能详细说明我如何修改它以满足我的需要吗?
  • (a) 将表从一个数据库镜像(例如复制)到另一个数据库或 (b) 在 PHP 中进行计数(但是上次我尝试将 MSSQL 数据库连接到 PHP,我发现它更容易改为导出/导入 MySQL 并连接 MySQL)
  • 另外,如果另一个人在不同的时间使用相同的分机登录,这会像上面那样工作吗?
  • 呃,现在我明白了。那是问题。 Solo SQL 解决方案将“太复杂”,或者您可以像其他人暗示的那样使用缓存来做这件事。我个人会在 PHP 中并排读取两个排序查询的方法,以防您以某种方式设法在 PHP 中连接 MSSQL(我听说 PDO 插件可以做到这一点,不知何故)。
【解决方案2】:
$q1="SELECT USERNAME, EXTENSION, unix_timestamp(LOGGEDIN) as t FROM table1 WHERE 1 ORDER BY EXTENSION,LOGGEDIN";

$q2="
(SELECT SRC-0 as EXTENSION, 0 as side, unix_timestamp(`TIME`) as t FROM table2 WHERE CHAR_LENGTH(SRC)=3 )
UNION
(SELECT DST-0 as EXTENSION, 1 as side, unix_timestamp(`TIME`) as t FROM table2 WHERE CHAR_LENGTH(DST)=3 )
ORDER BY EXTENSION, t";


$r1 = $db1->query($q1);
$r2 = $db2->query($q2);

$x1 = $r1->fetch_object();
$x2 = $r2->fetch_object();

$users = array();

$future_x1 = $r1->fetch_object();

while($x1 && $x2)
{
    if( $x1->EXTENSION < $x2->EXTENSION )
    {
        $x1=$future_x1 ;
        $future_x1=$r1->fetch_object();
    }
    elseif( $x1->EXTENSION > $x2->EXTENSION )
    {
        $x2 = $r2->fetch_object();
    }
    elseif( $future_x1 && $future_x1->EXTENSION == $x1->EXTENSION && $x2->t >= $future_x1->t )
    {
        $x1=$future_x1 ;
        $future_x1=$r1->fetch_object();
    }
    else
    {
        @$users[$x1->USERNAME][$x2->side]++;
        $x2 = $r2->fetch_object();
    }
}

print_r($users);

此解决方案假定您能够从 PHP 连接到两个数据库,并且可以负担得起从两个表中读取几乎所有行并保存一个大小等于用户名数量的数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多