从sqlite数据库中选择不同的值对

时间:2013-12-11 09:01:15

标签: sql sqlite

我有一个sqlite数据库,其表结构如下

第1列:源IP
第2列:源端口
第3列:目标IP
第4列:目标端口
第5列:协议
第6列:类型

表的快照如下所示

╔═══╦══════╦═══╦═════╦═════╦═══╗
║ A ║ 444  ║ B ║ 555 ║ TCP ║ 2 ║
╠═══╬══════╬═══╬═════╬═════╬═══╣
║ B ║ 555  ║ A ║ 444 ║ TCP ║ 1 ║
╠═══╬══════╬═══╬═════╬═════╬═══╣
║ C ║ 100  ║ A ║ 5525║ UDP ║ 1 ║
╠═══╬══════╬═══╬═════╬═════╬═══╣
║ B ║ 5222 ║ C ║ 2552║ TCP ║ 2 ║
╠═══╬══════╬═══╬═════╬═════╬═══╣
║ A ║ 5525 ║ C ║ 100 ║ UDP ║ 2 ║
╠═══╬══════╬═══╬═════╬═════╬═══╣
║ C ║ 2552 ║ B ║ 5222║ TCP ║ 1 ║
╚═══╩══════╩═══╩═════╩═════╩═══╝

在上表中,您可以看到(A,444),(B,555)和(B,555),(A,444)都有条目。 我想选择不同的[(源IP,源端口),(目标IP,目标端口),(协议)],即,我想要一个提供如下输出的查询

╔═══╦══════╦═══╦═════╦═════╦═══╗
║ A ║ 444  ║ B ║ 555 ║ TCP ║ 2 ║
╠═══╬══════╬═══╬═════╬═════╬═══╣
║ B ║ 5222 ║ C ║ 2552║ TCP ║ 2 ║
╠═══╬══════╬═══╬═════╬═════╬═══╣
║ C ║ 100  ║ A ║ 5525║ UDP ║ 1 ║
╚═══╩══════╩═══╩═════╩═════╩═══╝

提前致谢

1 个答案:

答案 0 :(得分:3)

以下将做:

SELECT *,
    source_ip<destination_ip OR source_ip=destination_ip AND source_port<destination_port AS _asc
FROM _table
GROUP BY
    CASE WHEN _asc THEN source_ip ELSE destination_ip END,
    CASE WHEN _asc THEN source_port ELSE destination_port END,
    CASE WHEN _asc THEN destination_ip ELSE source_ip END,
    CASE WHEN _asc THEN destination_port ELSE source_port END;

编辑:关注您的编辑...

SELECT *
FROM (
  SELECT *,
      source_ip<destination_ip OR source_ip=destination_ip AND source_port<destination_port AS _asc
  FROM _table
  ORDER BY ROWID DESC
)
GROUP BY
    CASE WHEN _asc THEN source_ip ELSE destination_ip END,
    CASE WHEN _asc THEN source_port ELSE destination_port END,
    CASE WHEN _asc THEN destination_ip ELSE source_ip END,
    CASE WHEN _asc THEN destination_port ELSE source_port END;

可能工作,但是

  1. “第一行”在数据库上下文中没有意义,因为ROWID可能会发生变化。 “第一”仅在应用于色谱柱时才有意义,例如: “第一个端口号”或“首先按日期添加” - 这意味着您可能需要另一个列。

  2. 虽然SQLite选择为每个组选择最后一行(对于非聚合表达式),但不保证这种行为将在不同版本中保持或保持一致。

  3. 签入SQL Fiddle