请问如何获得GridView选中行的每一列的信息?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请问如何获得GridView选中行的每一列的信息?相关的知识,希望对你有一定的参考价值。

参考技术A 1、
先在GridView上绑定datakeysName把ID绑上去
2、
加个选择列
在GridView的SelectedIndexChanging时间中获得选择行的ID
方法是:
int.Parse(this.GridView1.DataKey.[e.RowIndex].Value.ToString());
3、
然后根据ID查出来,一个一个赋值到文本框中

检索行的每一列的最后一个已知值

【中文标题】检索行的每一列的最后一个已知值【英文标题】:Retrieve last known value for each column of a row 【发布时间】:2013-12-13 07:37:22 【问题描述】:

不确定问这个问题的正确词,所以我会分解它。

我有一张如下表:

date_time | a | b | c

最后 4 行:

15/10/2013 11:45:00 | null   | 'timtim' | 'fred'
15/10/2013 13:00:00 | 'tune' | 'reco'   | null
16/10/2013 12:00:00 | 'abc'  | null     | null
16/10/2013 13:00:00 | null   | 'died'   | null

我将如何获取最后一条记录,但其值忽略空值,而是从上一条记录中获取值。

在我提供的示例中,返回的行将是

16/10/2013 13:00:00 | 'abc' | 'died' | 'fred'

如您所见,如果一列的值为空,那么它将转到具有该列值并使用该值的最后一条记录。

这应该是可能的,我只是想不通。到目前为止,我只提出了:

select 
    last_value(a) over w a
from test
WINDOW w AS (
    partition by a
    ORDER BY ts asc
    range between current row and unbounded following
    );

但这仅适用于单个列...

【问题讨论】:

最后一个数据是插入的顺序还是最大日期时间? 最后一条数据是插入的顺序 表格中没有自然顺序。表是没有顺序的集合。只要您不在某处存储该信息,"last data is the order that was inserted" 就不会被定义。 CTID不可靠。它可以通过任何更新或恢复随时更改。 【参考方案1】:

行的顺序

需要明确定义“最后一行”和排序顺序。集合(或表格)中没有自然顺序。我假设ORDER BY ts,其中 ts 是时间戳列。 像@Jorge pointed out in his comment:如果ts 不是UNIQUE,则需要为排序顺序定义决胜局以使其明确(向ORDER BY 添加更多项目)。主键将是最终的解决方案。

使用窗口函数的一般解决方案

要获得每一行行的结果:

SELECT ts
     , max(a) OVER (PARTITION BY grp_a) AS a
     , max(b) OVER (PARTITION BY grp_b) AS b
     , max(c) OVER (PARTITION BY grp_c) AS c
FROM (
   SELECT *
        , count(a) OVER (ORDER BY ts) AS grp_a
        , count(b) OVER (ORDER BY ts) AS grp_b
        , count(c) OVER (ORDER BY ts) AS grp_c
   FROM t
   ) sub;

如何?

聚合函数count() 在计数时会忽略 NULL 值。用作聚合窗口函数,它根据default window definition, which is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 计算列的运行计数。 NULL 值不会增加计数,因此这些行与最后一个非 null 值属于同一对等组。 在第二个窗口函数中,使用max() 或 min() 可以轻松提取每组唯一的非空值。

就在最后一行

WITH cte AS (
   SELECT *
        , count(a) OVER w AS grp_a
        , count(b) OVER w AS grp_b
        , count(c) OVER w AS grp_c
   FROM   t
   WINDOW w AS (ORDER BY ts)
   ) 
SELECT ts
     , max(a) OVER (PARTITION BY grp_a) AS a
     , max(b) OVER (PARTITION BY grp_b) AS b
     , max(c) OVER (PARTITION BY grp_c) AS c
FROM   cte
ORDER  BY ts DESC
LIMIT  1;

最后一行的简单替代方案

SELECT ts
      ,COALESCE(a, (SELECT a FROM t WHERE a IS NOT NULL ORDER BY ts DESC LIMIT 1)) AS a
      ,COALESCE(b, (SELECT b FROM t WHERE b IS NOT NULL ORDER BY ts DESC LIMIT 1)) AS b
      ,COALESCE(c, (SELECT c FROM t WHERE c IS NOT NULL ORDER BY ts DESC LIMIT 1)) AS c
FROM   t
ORDER  BY ts DESC
LIMIT  1;

或者:

SELECT (SELECT ts FROM t                     ORDER BY ts DESC LIMIT 1) AS ts
      ,(SELECT a  FROM t WHERE a IS NOT NULL ORDER BY ts DESC LIMIT 1) AS a
      ,(SELECT b  FROM t WHERE b IS NOT NULL ORDER BY ts DESC LIMIT 1) AS b
      ,(SELECT c  FROM t WHERE c IS NOT NULL ORDER BY ts DESC LIMIT 1) AS c

db小提琴here旧sqlfiddle

性能

虽然这应该很快,但如果性能是您的首要要求,请考虑使用 plpgsql 函数。从最后一行开始并循环降序,直到所需的每一列都有一个非空值。沿着这些思路:

GROUP BY and aggregate sequential numeric values

【讨论】:

您的答案无法正常工作。看到这个测试:sqlfiddle.com/#!12/4ba24/1 @JorgeCampos:当然可以。您的示例仅表明如果 ts 不是 UNIQUE,则仅按时间戳列 ts 的排序是未明确定义。在这方面的问题是不清楚的。就像您认为的那样,RDBMS 的表中没有自然顺序。通过 CTID 订购并非不可靠。顺便说一句,我添加了没有窗口功能的简单版本。 我想你误会了我,我喜欢你的回答,比我自己的要优雅得多。我之所以指出这一点,是因为与 OP 关于 cmets 的讨论。我只是指出,所以你可以修复。如果您解决此问题,我希望看到 OP 取消标记我的答案并标记您的答案。正如我所说,我的答案是一个丑陋的解决方案。 :) @JorgeCampos:嗯,谢谢你的提琴。为此,我添加了一段来澄清排序顺序的问题。【参考方案2】:

在这里,我创建了一个将列收集到数组中的聚合函数。然后只需删除 NULL 并从每个数组中选择最后一个元素。

样本数据

CREATE TABLE T (
    date_time timestamp,
    a text,
    b text,
    c text
);

INSERT INTO T VALUES ('2013-10-15 11:45:00', NULL, 'timtim', 'fred'),
('2013-10-15 13:00:00', 'tune', 'reco', NULL  ),
('2013-10-16 12:00:00', 'abc', NULL, NULL     ),
('2013-10-16 13:00:00', NULL, 'died', NULL    );

解决方案

CREATE AGGREGATE array_accum (anyelement)
(
    sfunc = array_append,
    stype = anyarray,
    initcond = ''
);

WITH latest_nonull AS (
    SELECT MAX(date_time) As MaxDateTime, 
           array_remove(array_accum(a), NULL) AS A, 
           array_remove(array_accum(b), NULL) AS B, 
           array_remove(array_accum(c), NULL) AS C
    FROM T
    ORDER BY date_time
)
SELECT MaxDateTime, A[array_upper(A, 1)], B[array_upper(B,1)], C[array_upper(C,1)]
FROM latest_nonull;

结果

     maxdatetime     |  a  |  b   |  c
---------------------+-----+------+------
 2013-10-16 13:00:00 | abc | died | fred
(1 row)

【讨论】:

如果最后一个注册表的日期是 15/10/2013 11:45:00 会起作用吗? 抱歉,我是 postgres 新手,当我尝试创建聚合时,我收到错误 ERROR: function array_prepend(anyarray, anyelement) does not exist SQL state: 42883 @JorgeCampos 不,我没有看到问题下的 cmets。我会修复它。这假设最后一次插入是最新的时间戳。 @cghrmauritius 这是一个错字,如果你现在查看代码,它有 array_append 而不是 array_prepend) ok 似乎到了某个地方,我已经设法创建了聚合谢谢,但是 with iss throwing ERROR: function array_remove(text[], unknown) does not exist SQL state: 42883 提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。字符:72【参考方案3】:

这应该可行,但请记住这是一个丑陋的解决方案

select * from
(select dt from
(select rank() over (order by ctid desc) idx, dt
  from sometable ) cx
where idx = 1) dtz,
(
select a from
(select rank() over (order by ctid desc) idx, a
  from sometable where a is not null ) ax 
where idx = 1) az,
(
select b from
(select rank() over (order by ctid desc) idx, b
  from sometable where b is not null ) bx 
where idx = 1) bz,
(
select c from
(select rank() over (order by ctid desc) idx, c
  from sometable where c is not null ) cx
where idx = 1) cz

在 fiddle 看到它:http://sqlfiddle.com/#!15/d5940/40

结果是

DT                                   A        B      C
October, 16 2013 00:00:00+0000      abc     died    fred

【讨论】:

这建立在不存在的“自然秩序”之上。此外,您根本不需要这种方法的窗口函数。考虑一下我的回答中的“简单替代方案”。

以上是关于请问如何获得GridView选中行的每一列的信息?的主要内容,如果未能解决你的问题,请参考以下文章

gridview控件,怎么点击选中,获取行的数据?

如何从C#中获取ListView中选中某一行某一列的值

Android 利用ListView制作带竖线的多彩表格

我想请教你 我想实现 点击全选的时候 dev控件GridControl 中的每一列都被选中 并且我如何获取是不是选中

获取gridview选中行的数据

如何通过点击datagridview的一行,获得这一行中的数据?c#高手指教