Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   .NET (https://www.clubdelphi.com/foros/forumdisplay.php?f=17)
-   -   Registros distintos en DataTable (https://www.clubdelphi.com/foros/showthread.php?t=95480)

elrayo76 01-12-2021 18:31:34

Registros distintos en DataTable
 
Buenas en esta oportunidad me toco desarrollar algo en C# y tengo una cuestión que no puedo resolver.

Digamos que tengo un DataTable con algunos registros y las siguientes columnas

Ramo | Producto | Poliza | Descripcion | ......
1730 1 200 Pruebas 2
1730 1 200 Pruebas
1730 1 200 Pruebas 2
1730 1 120 Pruebas

Digamos que mas o menos esos son los datos que puede tener el DataTable. Ahora bien, como se puede hacer con LINQ o Lambda para que yo pueda saber si los registros agrupados por Ramo/Producto/Poliza tienen alguno con la descripción distinta.

Para el ejemplo que puse me debería devolver que existen registros con distinta descripción (1730/1/200). No me importa saber en que grupo de registros es el problema en este caso, solo saber que no cumplen con la condición esperada.

Esto que planteo es porque levanto un Excel que paso a un DataTable y los registros con la misma agrupación (Ramo/Producto/Poliza) tienen que tener algunos de sus campos iguales para que se pueda importar luego a la base de datos (ejemplo: la descripción).

¿De no ser tan fácil de resolver con lo que pido, que otra forma de hacerlo se les ocurre?.

Espero haberme hecho entender. Cualquier cosa me dicen.

Saludos,
El Rayo

Casimiro Notevi 01-12-2021 19:12:16

No he entendido el problema ni lo que quieres conseguir.

elrayo76 01-12-2021 19:34:42

Bien, veamos ahora.

El problema si te fijas es el ejemplo que puse es que existen registros con mismo Ramo/Producto/Poliza que tienen diferente descripción. Además existen diferentes números de Polizas como se puede ver.

Dentro de cada uno de esos números de pólizas la descripción debe ser única (esto en el ejemplo, en mi caso es otro dato). Como puedo hacer para detectar cuando dentro de una misma póliza existen diferentes descripciones y así informar al usuario.

Yo pensaba hacerlo en el DataTable con LINQ, pero no se si es tan fácil.

Espero haberme hecho entender.

Saludos,
El Rayo

Casimiro Notevi 01-12-2021 20:53:48

O sea, con este ejemplo:
Código:

1730      1          200        Pruebas 2
 1730      1          200        Pruebas
 1730      1          200        Pruebas 2
 1730      1          120        Pruebas

Debería devolver:
Código:

1730      1          200        Pruebas 2
 1730      1          200        Pruebas

¿Es eso lo que quieres?

mamcx 01-12-2021 21:14:12

Pues hazlo con linq? Es muy similar a sql. Que has intentado?

P.D: Puedes poner el ejemplo en https://dotnetfiddle.net/akUcWR

elrayo76 01-12-2021 21:20:45

Digamos que si, porque si todos los registros del 200 tuvieran las misma descripción no debería mostrarlos. Como lo dices parece fácil pero el tema es que no se tiene datos como para poder filtrar (por la Poliza agrupada) el DataTable mas que con lo que tiene si mismo.

Si por ejemplo poliza 120 tuviera mas de 1 registro con la misma descripción tampoco debería mostrarlo, solo saldría si descripción fuera distinta.

Pido disculpas si no me supe explicar bien. Hay veces que uno tiene las cosas en la cabeza y bajarlas para explicarlas no es tan simple.

Saludos

elrayo76 01-12-2021 21:56:26

Lo que he podido realizar hasta ahora es lo siguiente

Código:

                var Records = ExcelTable.AsEnumerable()
                    .GroupBy(g => new
                    {
                        Branch = g["Ramo"],
                        Product = g["Producto"],
                        Policy = g["Poliza"],
                        Descrip = g["Descripcion"],
                    })
                    .Select(r =>
                    {
                        var row = ExcelTable.NewRow();
                        row["Ramo"] = r.Key.Branch;
                        row["Producto"] = r.Key.Product;
                        row["Poliza"] = r.Key.Policy;
                        row["Descripcion"] = r.Key.Descrip;
                        return row;
                    });

Esto me está devolviendo todos los grupos, incluidos los que no necesito. No se como realizar la parte que me falta para que solo queden como en el ejemplo de Casimiro

Saludos

mamcx 02-12-2021 19:12:42

El problema fundamental es que los datos no tienen claro cual es su unicidad. Hice un ejemplo en:

https://dotnetfiddle.net/PSiEN5

Código PHP:

using System;
using System.Linq;
using System.Collections.Generic;

class 
Tabla
{
    public 
int ramo;
    public 
int producto;
    public 
int poliza;
    public 
string descripcion;
}

public class 
Program
{
    public static 
void Main()
    {
        List<
Tablarecords = new List<Tabla>()
        {new 
Tabla{ramo 1730producto 1poliza 200descripcion "Pruebas 2"}, new Tabla{ramo 1730producto 1poliza 200descripcion "Pruebas"}, new Tabla{ramo 1730producto 1poliza 200descripcion "Pruebas 2"}, new Tabla{ramo 1730producto 1poliza 120descripcion "Pruebas"}, };
        List<
Tabla= (
            
from row in records
            orderby row
.ramorow.productorow.poliza descendingrow.descripcion descending
            group row by 
new
            {
            
row.ramorow.productorow.poliza
            
}
                
into t
                select 
new Tabla()
                {
ramo t.Key.ramoproducto t.Key.producto
                 
poliza t.Key.polizadescripcion t.ToList().FirstOrDefault().descripcion}).ToList();
        
        foreach (
Tabla item in q)
        {
            
Console.Write(item.ramo);
            
Console.Write(item.producto);
            
Console.Write(item.poliza);
            
Console.WriteLine(item.descripcion);
        }
    }


Código:

17301200Pruebas 2
17301120Pruebas

Como vez, no da exacto con Casimiro porque el resultado que pone tiene ambigüedad con los datos que tienes.

Tu ejemplo anterior dice que todos los campos hay que agruparlos, pero eso no coincide con los resultados posibles. Dependiendo de qué campos y de que orden se cambia el resultado, PERO, es AMBIGUO! Con mas datos dudo de que sea estable la solución!

La solución es encontrar cómo diferenciar los datos y asignarles un ORDEN/RANK.

Describes que estos datos NO SON los reales y que usaste un ejemplo? Si es asi, solo estas complicando la solucion. Por ejemplo, es muy dificil usando STRING determinar el orden/ranking porque su orden esta basado en reglas de idiomas humanos.

elrayo76 02-12-2021 19:47:31

mamcx gracias por la respuesta.

Entiendo todo lo que dices. El tema es que en el Excel que importa el usuario hay datos como Ramo/Producto/Poliza que son los que se toman como clave para agrupar. Estos grupos pueden tener columnas donde sus datos deben ser todos iguales, en otras columnas si son distintos no hay problema.

En el caso de encontrar un dato distinto en alguna columna donde deben ser todos iguales se le debe avisar al usuario y se anula todo el proceso de importación.

Igualmente gracias nuevamente por lo comentado. Voy a ver como lo soluciono. Cualquier cosa veré si es mas fácil hacerlo del lado de la base de datos y lo propondré al analista a ver que dice.

Saludos
El Rayo

mamcx 03-12-2021 00:46:51

Ah ok, entonces el asunto es MAS simple. Si es un error, solo necesitas es filtrar los que tienen mas de 1 registro:

Código PHP:

using System;
using System.Linq;
using System.Collections.Generic;

class 
Tabla
{
    public 
int ramo;
    public 
int producto;
    public 
int poliza;
    public 
string descripcion;
}

class 
Result
{
    public 
int ramo;
    public 
int producto;
    public 
int poliza;
    public 
int total;
}

public class 
Program
{
    public static 
void Main()
    {
        List<
Tablarecords = new List<Tabla>()
        {new 
Tabla{ramo 1730producto 1poliza 200descripcion "Pruebas 2"}, new Tabla{ramo 1730producto 1poliza 200descripcion "Pruebas"}, new Tabla{ramo 1730producto 1poliza 200descripcion "Pruebas 2"}, new Tabla{ramo 1730producto 1poliza 120descripcion "Pruebas"}, };
        List<
Result= (
            
from row in records
            orderby row
.ramorow.productorow.poliza descendingrow.descripcion descending
            group row by 
new
            {
            
row.ramorow.productorow.poliza
            
}

                
into t
                select 
new Result()
                {
ramo t.Key.ramoproducto t.Key.productopoliza t.Key.polizatotal t.Count()});
        
        foreach (
Result item in q)
        {
            if (
item.total 1)
            {
                
Console.Write(item.ramo);
                
Console.Write(item.producto);
                
Console.Write(item.poliza);
            }
        }
    }




La franja horaria es GMT +2. Ahora son las 23:15:10.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi