¿Hay alguna diferencia entre GROUP BY y DISTINCT?


310

Aprendí algo simple sobre SQL el otro día:

SELECT c FROM myTbl GROUP BY C

Tiene el mismo resultado que:

SELECT DISTINCT C FROM myTbl

De lo que tengo curiosidad, ¿hay algo diferente en la forma en que un motor SQL procesa el comando, o son realmente lo mismo?

Personalmente prefiero la sintaxis distinta, pero estoy seguro de que es más un hábito que otra cosa.

EDITAR: Esta no es una pregunta sobre agregados. Se GROUP BYentiende el uso de con funciones agregadas.


11
Esta no es una pregunta sobre los agregados, es un GROUP BY que funciona igual que un distinto cuando no hay una función de agregado
Brettski

2
También puede hacer SELECT c FROM myTbl UNION SELECT c FROM myTbly obtener el mismo resultado ... Pero ¿por qué complicar las cosas cuando SELECT DISTINCT es tan fácil?
jarlh

El 'orden lógico de ejecución' de GROUP BYes mucho antes que 'SELECCIONAR' y DISTINCTsigue a seleccionar.
Used_By_Already

Una diferencia muy pequeña que no he visto mencionada es que DISTINCTen realidad se selecciona el campo, es decir, el valor aparecerá en el conjunto de resultados. GROUP BYpuede eliminar efectivamente duplicados sin seleccionar realmente el campo. Esto es algo irrelevante en la mayoría de los casos, pero podría ser exactamente lo que desea en otros. Si termina usando GROUP BYen lugar de DISTINCT, probablemente se justifique un comentario explicativo en el código.
rinogo

La conclusión parece ser que debido a que la eliminación de duplicados ocurre en diferentes puntos del plan de ejecución, uno puede ser más eficiente que el otro porque la eliminación de duplicación requiere una especie o quizás el uso de este índice sobre ese índice. Por lo tanto, puede haber una ventaja de la eliminación temprana de dup o la ventaja puede ser el uso de un índice diferente desde el principio y comer un tipo más tarde cuando quedan pocas filas y la clasificación es insignificante.
bielawski

Respuestas:


246

La respuesta de MusiGenesis es funcionalmente la correcta con respecto a su pregunta como se indicó; SQL Server es lo suficientemente inteligente como para darse cuenta de que si está usando "Agrupar por" y no está usando ninguna función agregada, entonces lo que realmente quiere decir es "Distinto", y por lo tanto genera un plan de ejecución como si simplemente hubiera usado "Distincto" ".

Sin embargo, creo que es importante tener en cuenta la respuesta de Hank también: el trato arrogante de "Group By" y "Distinct" podría conducir a algunas trampas perniciosas si no tienes cuidado. No es del todo correcto decir que esta "no es una pregunta sobre agregados" porque está preguntando acerca de la diferencia funcional entre dos palabras clave de consulta SQL, una de las cuales está destinada a usarse con agregados y otra no.

Un martillo puede funcionar para clavar un tornillo a veces, pero si tiene un destornillador a mano, ¿por qué molestarse?

(a los efectos de esta analogía, Hammer : Screwdriver :: GroupBy : Distincty screw => get list of unique values in a table column)


Estoy totalmente de acuerdo con usted, Skeolan. Me sorprendió bastante cuando me encontré con esta funcionalidad. No es algo que planeo usar, sino una forma de hacer las cosas en este nuevo lugar en el que estoy trabajando.
Brettski

Al menos en Oracle 12 parece haber casos en los que DISTINCT, obteniendo valores distintos por UNION y GROUP BY funcionan de manera diferente. Hoy tuve un caso en el que DISTINCT y distinto por UNION causan un error de oráculo, pero GROUP BY funcionó; Estaba seleccionando solo 1 columna de una vista y no estaba usando ninguna agregación; Todavía estoy desconcertado por qué lo requirió, pero confirma que hay alguna diferencia en la ejecución. Como otros señalan, también le permite AGRUPAR POR columnas que no están en la selección, aunque eso rara vez sería necesario sin la agregación.
ZeroK

1
Cuando se trata de SQL, siempre tiene disponibles un destornillador y un martillo. ¿Por qué usar un martillo para clavar un tornillo?
jarlh

Para ser claros con respecto a su analogía: ¿su martillo == GroupBy y su destornillador == son distintos en este caso?
HopeKing

¡Guau, esta pregunta de diez años todavía tiene piernas! "Distintivo" es el destornillador, si "lista de valores únicos" es el tornillo. Actualizaré la respuesta para aclarar la analogía.
Skeolan

136

GROUP BYle permite utilizar las funciones de agregado, como AVG, MAX, MIN, SUM, y COUNT. Por otro lado DISTINCTsolo elimina los duplicados.

Por ejemplo, si tiene un montón de registros de compras y desea saber cuánto gastó cada departamento, puede hacer algo como:

SELECT department, SUM(amount) FROM purchases GROUP BY department

Esto le dará una fila por departamento, que contiene el nombre del departamento y la suma de todos los amountvalores en todas las filas para ese departamento.


2
El uso de GROUP BY Entiendo, la pregunta se basa en el hecho de que devuelve un conjunto de datos distinto cuando no hay una función agregada presente.
Brettski

2
Porque GROUP BY hace una DISTINCIÓN implícita sobre los valores de la columna por la que está agrupando (perdón por la cacofonía).
Joe Pineda

¿No es posible usar DISTINCT+ a funciones agregadas? así:select distinct department, SUM(amount) from ...
Shafizadeh

@Sajad, puedes hacer eso sí, pero aún tienes que tener GROUP BY, por lo que DISTINCT no hace nada por ti.
ZeroK


40

¿Cuál es la diferencia desde un simple punto de vista de funcionalidad de eliminación duplicada?

Además del hecho de que DISTINCT, a diferencia , GROUP BYpermite agregar datos por grupo (que ha sido mencionado por muchas otras respuestas), la diferencia más importante en mi opinión es el hecho de que las dos operaciones "suceden" en dos pasos muy diferentes en el orden lógico de operaciones que se ejecutan en una SELECTdeclaración .

Estas son las operaciones más importantes:

  • FROM(incluyendo JOIN, APPLY, etc.)
  • WHERE
  • GROUP BY (puede eliminar duplicados)
  • Agregaciones
  • HAVING
  • Funciones de ventana
  • SELECT
  • DISTINCT (puede eliminar duplicados)
  • UNION, INTERSECT, EXCEPT (Se puede eliminar duplicados)
  • ORDER BY
  • OFFSET
  • LIMIT

Como puede ver, el orden lógico de cada operación influye en lo que se puede hacer con él y cómo influye en las operaciones posteriores. En particular, el hecho de que la GROUP BYoperación "ocurre antes" de la SELECToperación (la proyección) significa que:

  1. No depende de la proyección (que puede ser una ventaja)
  2. No puede usar ningún valor de la proyección (lo que puede ser una desventaja)

1. No depende de la proyección.

Un ejemplo en el que no es útil depender de la proyección es si desea calcular funciones de ventana en valores distintos:

SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating

Cuando se ejecuta contra la base de datos Sakila , esto produce:

rating   rn
-----------
G        1
NC-17    2
PG       3
PG-13    4
R        5

No se podría lograr lo mismo DISTINCTfácilmente:

SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film

Esa consulta es "incorrecta" y produce algo como:

rating   rn
------------
G        1
G        2
G        3
...
G        178
NC-17    179
NC-17    180
...

Esto no es lo que queríamos. La DISTINCToperación "ocurre" después de la proyección, por lo que ya no podemos eliminar las DISTINCTcalificaciones porque la función de ventana ya se calculó y proyectó. Para usar DISTINCT, tendríamos que anidar esa parte de la consulta:

SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
  SELECT DISTINCT rating FROM film
) f

Nota al margen: en este caso particular, también podríamos usarDENSE_RANK()

SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film

2. No puede usar ningún valor de la proyección

Uno de los inconvenientes de SQL es su verbosidad a veces. Por la misma razón que hemos visto antes (es decir, el orden lógico de operaciones), no podemos agrupar "fácilmente" por algo que estamos proyectando.

Esto es SQL inválido:

SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name

Esto es válido (repitiendo la expresión)

SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name

Esto también es válido (anidando la expresión)

SELECT name
FROM (
  SELECT first_name || ' ' || last_name AS name
  FROM customer
) c
GROUP BY name

He escrito sobre este tema con mayor profundidad en una publicación de blog.


Sinceramente, me sorprendió ver que el orden de ejecución no se discutió de inmediato sobre esta cuestión. Gracias, muy bien explicado también. En su punto 2. algunos (¿uno?) Db permiten el uso de alias selectos a lo largo de la consulta (el que conozco es Teradata, pero es una excepción).
Used_By_Already

@Used_By_Already: Claro, algunas bases de datos hacen eso. Muchas bases de datos permiten el uso de esos alias solo en partes (por ejemplo, no WHEREpero tal vez GROUP BY). En cualquier caso, creo que es una mala idea y sugiero nunca usar esa función por razones de portabilidad y mantenimiento. "De repente" ya no funcionará, por ejemplo, al alias una función agregada o una función de ventana.
Lukas Eder

never using that feature for portability and maintenance reasons!! Estoy de acuerdo al 100% ... y ahora también estoy escribiendo tu blog, gran trabajo. Salud.
Used_By_Already

32

Úselo DISTINCTsi solo desea eliminar duplicados. Utilizar GROUPY BYsi desea aplicar operadores globales ( MAX, SUM, GROUP_CONCAT, ..., o una HAVINGcláusula).


19

Espero que exista la posibilidad de diferencias sutiles en su ejecución. Verifiqué los planes de ejecución para dos consultas funcionalmente equivalentes a lo largo de estas líneas en Oracle 10g:

core> select sta from zip group by sta;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH GROUP BY     |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

core> select distinct sta from zip;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH UNIQUE       |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

La operación intermedia es ligeramente diferente: "HASH GROUP BY" versus "HASH UNIQUE", pero los costos estimados, etc. son idénticos. Luego ejecuté estos con seguimiento y los recuentos de operaciones reales fueron los mismos para ambos (excepto que el segundo no tuvo que hacer ninguna lectura física debido al almacenamiento en caché).

Pero creo que debido a que los nombres de las operaciones son diferentes, la ejecución seguiría rutas de código algo diferentes y eso abre la posibilidad de diferencias más significativas.

Creo que debería preferir la sintaxis DISTINCT para este propósito. No es solo un hábito, sino que indica más claramente el propósito de la consulta.


14

Para la consulta que publicó, son idénticos. Pero para otras consultas que pueden no ser ciertas.

Por ejemplo, no es lo mismo que:

SELECT C FROM myTbl GROUP BY C, D

14

Leí todos los comentarios anteriores, pero no vi que nadie señalara la diferencia principal entre Group By y Distinct, aparte del bit de agregación.

Distinct devuelve todas las filas y luego las desduplica mientras que Group By desduplica las filas a medida que el algoritmo las lee una por una.

¡Esto significa que pueden producir resultados diferentes!

Por ejemplo, los siguientes códigos generan resultados diferentes:

SELECT distinct ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable

 SELECT ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable
GROUP BY Name

Si hay 10 nombres en la tabla donde 1 de los cuales es un duplicado de otro, la primera consulta devuelve 10 filas, mientras que la segunda consulta devuelve 9 filas.

¡La razón es lo que dije anteriormente para que puedan comportarse de manera diferente!


11
Esto se debe a que si bien solo está agrupando Nameen la segunda consulta, la distinctpalabra clave se aplica tanto a las columnas Namecomo a su ROW_NUMBER()columna en la selectcláusula de la primera consulta. Si también se hubiera agrupado por la primera columna en la segunda consulta, las consultas habrían devuelto los mismos resultados.

Este es un resultado de la order of executionde las cláusulas SQL que es (en un sentido general) FROM and ON (joins), WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY, LIMIT / OFFSET / TOPde modo que se aplica lo que resulta en una fila de la segunda consulta de los nombres se reducen en número por grupo por y más tarde el row_number () por nombre único En la primera consulta, se aplica row_number () antes de que se aplique el distintivo y, debido a la naturaleza de la función row_number (), cada fila obtiene un número entero único, por lo que cada fila se devuelve incluso si hay valores de nombre repetidos.
Used_By_Already

12

Si usa DISTINCT con varias columnas, el conjunto de resultados no se agrupará como lo hará con GROUP BY, y no puede usar funciones agregadas con DISTINCT.


11

Tienen una semántica diferente, incluso si tienen resultados equivalentes en sus datos particulares.


6

GROUP BY tiene un significado muy específico que es distinto (heh) de la función DISTINCT.

GROUP BY hace que los resultados de la consulta se agrupen utilizando la expresión elegida, las funciones agregadas se pueden aplicar y actuarán en cada grupo, en lugar de en todo el conjunto de resultados.

Aquí hay un ejemplo que podría ayudar:

Dada una tabla que se ve así:

name
------
barry
dave
bill
dave
dave
barry
john

Esta consulta:

SELECT name, count(*) AS count FROM table GROUP BY name;

Producirá resultados como este:

name    count
-------------
barry   2
dave    3
bill    1
john    1

Lo que obviamente es muy diferente de usar DISTINCT. Si desea agrupar sus resultados, use GROUP BY, si solo desea una lista única de una columna específica, use DISTINCT. Esto le dará a su base de datos la oportunidad de optimizar la consulta para sus necesidades.


6

No use GROUP BY cuando se refiera a DISTINCT, incluso si funcionan de la misma manera. Supongo que está tratando de reducir milisegundos de consultas, y debo señalar que el tiempo de desarrollador es mucho más costoso que el tiempo de computadora.


5

Si está utilizando GROUP BY sin ninguna función agregada, internamente se tratará como DISTINCT, por lo que en este caso no hay diferencia entre GROUP BY y DISTINCT.

Pero cuando se le proporciona la cláusula DISTINCT, es mejor usarla para encontrar sus registros únicos porque el objetivo de GROUP BY es lograr la agregación.


4

group by se usa en operaciones agregadas, como cuando desea obtener un recuento de Bs desglosado por la columna C

select C, count(B) from myTbl group by C

lo que suena distinto es: obtienes filas únicas.

En SQL Server 2005, parece que el optimizador de consultas es capaz de optimizar la diferencia en los ejemplos simplistas que ejecuté. No sé si puedes contar con eso en todas las situaciones, sin embargo.


3

En esa consulta en particular no hay diferencia. Pero, por supuesto, si agrega columnas agregadas, deberá usar group by.


3

En la perspectiva de Teradata :

Desde el punto de vista del resultado, no importa si usa DISTINCT o GROUP BY en Teradata. El conjunto de respuestas será el mismo.

Desde el punto de vista del rendimiento, no es lo mismo.

Para comprender qué afecta el rendimiento, debe saber qué sucede en Teradata al ejecutar una declaración con DISTINCT o GROUP BY.

En el caso de DISTINCT, las filas se redistribuyen inmediatamente sin que tenga lugar ninguna preagregación, mientras que en el caso de GROUP BY, en un primer paso se realiza una preagregación y solo entonces se redistribuyen los valores únicos entre los AMP.

No piense ahora que GROUP BY siempre es mejor desde el punto de vista del rendimiento. Cuando tiene muchos valores diferentes, el paso de preagregación de GROUP BY no es muy eficiente. Teradata tiene que ordenar los datos para eliminar duplicados. En este caso, puede ser mejor redistribuir primero, es decir, usar la instrucción DISTINCT. Solo si hay muchos valores duplicados, la instrucción GROUP BY es probablemente la mejor opción, ya que solo una vez que se realiza el paso de deduplicación, después de la redistribución.

En resumen, DISTINCT vs. GROUP BY en Teradata significa:

GROUP BY -> para muchos duplicados DISTINCT -> no hay o solo algunos duplicados. A veces, cuando usa DISTINCT, se queda sin espacio de cola en un AMP. La razón es que la redistribución se lleva a cabo de inmediato, y la inclinación podría hacer que los AMP se queden sin espacio.

Si esto sucede, probablemente tenga una mejor oportunidad con GROUP BY, ya que los duplicados ya se eliminan en un primer paso y se transfieren menos datos a través de los AMP.


¿Qué es Teradata?
Brettski

Teradata es un sistema de gestión de bases de datos relacionales (RDBMS), capaz de admitir muchos usuarios concurrentes de varias plataformas de clientes. Teradata es compatible con el estándar ANSI y está construido completamente en arquitectura paralela.
Ram Ghadiyaram

2

Desde la perspectiva de 'SQL the language', las dos construcciones son equivalentes y la que elija es una de esas elecciones de 'estilo de vida' que todos tenemos que tomar. Creo que hay un buen caso para que DISTINCT sea más explícito (y, por lo tanto, sea más considerado con la persona que heredará su código, etc.) pero eso no significa que la construcción GROUP BY sea una opción no válida.

Creo que este 'GROUP BY es para agregados' es el énfasis equivocado. La gente debe tener en cuenta que la función de configuración (MAX, MIN, COUNT, etc.) puede omitirse para que puedan comprender la intención del codificador cuando es así.

El optimizador ideal reconocerá construcciones SQL equivalentes y siempre elegirá el plan ideal en consecuencia. Para su motor SQL de la vida real de elección, debe probar :)

PS tenga en cuenta que la posición de la palabra clave DISTINCT en la cláusula select puede producir resultados diferentes, por ejemplo, contraste:

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;

1

Solo lo notas porque estás seleccionando una sola columna.

Intente seleccionar dos campos y vea qué sucede.

Group By está destinado a ser utilizado así:

SELECT name, SUM(transaction) FROM myTbl GROUP BY name

Lo que mostraría la suma de todas las transacciones para cada persona.


Esta no es una cuestión de agregados. En su ejemplo, SELECCIONE c, d DE mytbl GROUP POR C, D; de hecho devolverá el mismo conjunto de datos que SELECT DISTINCT C, D FROM mytbl; Estos son los fundamentos de la pregunta
Brettski el

1

Sé que es una publicación vieja. Pero sucede que tuve una consulta que usaba el grupo solo para devolver valores distintos al usar esa consulta en informes de sapo y Oracle, todo funcionó bien, me refiero a un buen tiempo de respuesta. Cuando migramos de Oracle 9i a 11g, el tiempo de respuesta en Toad fue excelente, pero en el informe tardó unos 35 minutos en finalizar el informe cuando se usaba la versión anterior, tardó unos 5 minutos.

La solución fue cambiar el grupo y usar DISTINCT y ahora el informe se ejecuta en aproximadamente 30 segundos.

Espero que esto sea útil para alguien con la misma situación.


1

En términos de uso, GROUP BY se usa para agrupar las filas que desea calcular. DISTINCT no hará ningún cálculo. No mostrará filas duplicadas.

Siempre usé DISTINCT si quiero presentar datos sin duplicados.

Si quiero hacer cálculos como resumir la cantidad total de mangos, usaré GROUP BY


0

La forma en que siempre lo entendí es que usar distinción es lo mismo que agrupar por cada campo que seleccionó en el orden en que los seleccionó.

es decir:

select distinct a, b, c from table;

es lo mismo que:

select a, b, c from table group by a, b, c

De acuerdo, pero sería lo mismo que seleccionar c, b, a del grupo de tabla por a, b, c
Dheer

Sí, sería lo mismo
Caius Jard

0

La eficiencia funcional es totalmente diferente. Si desea seleccionar solo el "valor de retorno", excepto uno duplicado, utilizar distintivo es mejor que agrupar por. Debido a que "agrupar por" incluye (ordenar + eliminar), "distinto" incluye (eliminar)



0

A veces pueden darle los mismos resultados, pero están destinados a ser utilizados en un sentido / caso diferente. La principal diferencia está en la sintaxis.

Observe minuciosamente el siguiente ejemplo. DISTINCTse usa para filtrar el conjunto duplicado de valores. (6, cs, 9.1) y (1, cs, 5.5) son dos conjuntos diferentes. Por DISTINCTlo tanto, se mostrarán ambas filas mientras GROUP BY Branchse mostrará solo un conjunto.

 SELECT * FROM student; 
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    2 | mech   |  6.3 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    1 | cs     |  5.5 |
+------+--------+------+
5 rows in set (0.001 sec)

SELECT DISTINCT * FROM student; 
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    2 | mech   |  6.3 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    1 | cs     |  5.5 |
+------+--------+------+
5 rows in set (0.001 sec)

SELECT * FROM student GROUP BY Branch;
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    3 | civil  |  7.2 |
|    6 | cs     |  9.1 |
|    4 | eee    |  8.2 |
|    2 | mech   |  6.3 |
+------+--------+------+
4 rows in set (0.001 sec)

A veces, los resultados que se pueden lograr mediante una GROUP BYcláusula no se pueden lograr DISTINCTsin utilizar alguna cláusula o condiciones adicionales. Por ejemplo, en el caso anterior.

Para obtener el mismo resultado DISTINCTque tiene que pasar todos los nombres de columna en la GROUP BYcláusula como a continuación. Entonces vean la diferencia sintáctica. Debe tener conocimiento sobre todos los nombres de columna para usar la GROUP BYcláusula en ese caso.

SELECT * FROM student GROUP BY Id, Branch, CGPA;
+------+--------+------+
| Id   | Branch | CGPA |
+------+--------+------+
|    1 | cs     |  5.5 |
|    2 | mech   |  6.3 |
|    3 | civil  |  7.2 |
|    4 | eee    |  8.2 |
|    6 | cs     |  9.1 |
+------+--------+------+

También he notado que GROUP BYmuestra los resultados en orden ascendente por defecto, lo DISTINCTque no ocurre. Pero no estoy seguro de esto. Puede ser diferente en cuanto al proveedor.

Fuente: https://dbjpanda.me/dbms/languages/sql/sql-syntax-with-examples#group-by


0

En general, podemos usar DISTINCTpara eliminar los duplicados en la columna específica de la tabla.

En caso de 'GROUP BY' podemos aplicar las funciones de agregación como AVG, MAX, MIN, SUM, y COUNTen la columna específica y buscar el nombre de la columna y la agregación resultado de la función en la misma columna.

Ejemplo:

select  specialColumn,sum(specialColumn) from yourTableName group by specialColumn;

-1

No existe una diferencia significativa entre el grupo por y la cláusula distinta, excepto el uso de funciones agregadas. Ambos se pueden utilizar para distinguir los valores, pero si en el punto de vista del rendimiento, el grupo es mejor. Cuando se usa una palabra clave distinta, internamente se usa una operación de clasificación que se puede ver en el plan de ejecución.

Prueba un ejemplo simple

Declarar la tabla @tmpresult (Id tinyint)

Insertar en @tmpresult Seleccionar 5 Unión todos Seleccionar 2 Unión todos Seleccionar 3 Unión todos Seleccionar 4

Seleccione un ID distinto de @tmpresult


distinto y grupal por ambas voluntades
vignesh
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.