Forum Doku Wiki Blog

Forumsarchiv 2005, Juli
Access: Having

archivierte Beiträge lesen

  1. (DATENBANK) Access: Having von Maresa P., 11. 07. 2005, 10:29

Access: Having

Der folgende Beitrag wurde am 11. 07. 2005, 10:29 Uhr von Maresa P. veröffentlicht.

Hallo liebes Forum,

ich habe folgendes Problem:

In einer Acces Datenbank habe ich zwei Tabellen:


user
------
username [text]



und

alleuser
------
username [text]



Ich möchte mir nun aus der Tabelle 'alleuser' alle 'username' ausgeben lassen, die nicht in der Tabelle user vorkommen.

Ich habe es folgendermaßen versucht:

SELECT alleuser.username
FROM alleuser INNER JOIN [user] ON alleuser.username = user.username
HAVING ((([user]![username])<>[alleuser]![username]));

Hier bekomme ich aber immer die Fehlermeldung 'Having Klausel ohne Gruppierung der Aggregatsfunktion'.

Wie funktioniert soetwas?


Vielen Dank für Euere Mühe
Maresa

Access: Having

Der folgende Beitrag wurde am 11. 07. 2005, 10:47 Uhr von Vinzenz Mai veröffentlicht.

Hallo Maresa

> Ich möchte mir nun aus der Tabelle 'alleuser' alle 'username' ausgeben lassen, die nicht in der Tabelle user vorkommen.
>
> Ich habe es folgendermaßen versucht:
>
> SELECT alleuser.username
> FROM alleuser INNER JOIN [user] ON alleuser.username = user.username

Für Dein Problem ist der LEFT OUTER JOIN, nicht der INNER JOIN zuständig :-)

> HAVING ((([user]![username])<>[alleuser]![username]));

Ersetze die HAVING-Klausel, die hier nicht zulässig ist, durch eine WHERE-Klausel.
Verwende als Kriterium IS NULL.


Freundliche Grüße

Vinzenz

Access: Having

Der folgende Beitrag wurde am 11. 07. 2005, 11:01 Uhr von Maresa P. veröffentlicht.

Hallo,

vielen Dank für Euere Hilfe.
Jetzt funktionierts!

Gruß
MAresa

Access: Having

Der folgende Beitrag wurde am 11. 07. 2005, 10:48 Uhr von Frank (no reg) veröffentlicht.

Hi,

"HAVING" kann nur in Zusammenhang mit der Aggregatsfunktion "GROUP BY" verwendet werden und wird erst zuletzt auf das Resultset angewendet.

Wie wär's mit folgendem


SELECT [alleuser].[username]
FROM [alleuser]
WHERE [alleuser].[username] NOT IN
  (SELECT [user].[username] FROM [user])


Grüße,
Frank

Access: Having

Der folgende Beitrag wurde am 11. 07. 2005, 11:04 Uhr von Vinzenz Mai veröffentlicht.

Hallo Frank

> Wie wär's mit folgendem
>
>
> SELECT [alleuser].[username]
> FROM [alleuser]
> WHERE [alleuser].[username] NOT IN
>   (SELECT [user].[username] FROM [user])
>


Sowas hört sich immer schrecklich unperformat an (ich weiß nicht, ob dies auch tatsächlich der Fall ist). Das sieht stets so aus, als würde jeder Datensatz aus alleuser mit vielen Datensätzen aus user verglichen wird. Keine Ahnung, was der Optimierer daraus macht.

Für mich ist sowas stets ein LEFT OUTER JOIN in Kombination mit der Bedingung IS NULL.


Freundliche Grüße

Vinzenz

Subqueries / Joins ...

Der folgende Beitrag wurde am 11. 07. 2005, 12:06 Uhr von Frank (no reg) veröffentlicht.

Hi,

in Bezug auf Access kann ich dir das leider nicht sagen, was SQL Server betrifft, sind die Ausführungspläne und damit die Kosten ziemlich ähnlich. Beide verwenden ein Hash-Match, die Outer-Join Variante mit der doppelten verarbeiteten Zeilenmenge plus einem zusätzlichen Filter-Schritt.

Ausgabe vom Trace:

SELECT userName FROM allUsers  WHERE allUsers.userName
NOT IN (SELECT userName FROM Users)
SQL:StmtCompleted 47 16 91 0

SELECT allUsers.userName FROM allUsers
LEFT OUTER JOIN Users ON allUsers.userName = Users.userName
WHERE Users.userName IS NULL
SQL:StmtCompleted 63 47 91 0

1. Spalte = Statement Duration
2. Spalte = CPU
3./4. Spalte = Logical Reads / Writes

Nachfolgend der TestCode:
=========================


CREATE DATABASE userTest
GO

USE userTest
GO

CREATE TABLE allUsers (
  userId int NOT NULL IDENTITY(0,1) PRIMARY KEY,
  userName varchar(50) NOT NULL,
)
GO

CREATE TABLE Users (
  userId int NOT NULL IDENTITY(0,1) PRIMARY KEY,
  userName varchar(50) NOT NULL,
)
GO

ALTER FUNCTION getUserName
(
  @intValue int
)
RETURNS varchar(50)
AS BEGIN
  DECLARE @returnName varchar(50)
  SET @returnName = ''

  WHILE @intValue <> 0 BEGIN
    DECLARE @rest int
    SET @rest = @intValue % 14

    IF @rest < 10
      SET @returnName = CHAR(48+@rest) + @returnName -- add a number
    ELSE IF @rest < 14
      SET @returnName = CHAR(65+(@rest-10)) + @returnName -- add a letter

    SET @intValue = @intValue/14
  END

  RETURN @returnName
END
GO

SELECT dbo.getUserName(156554645)

DECLARE @counter int
SET @counter = 2990000

WHILE (@counter < 3000000) BEGIN
  DECLARE @myName varchar(50)
  SET @myName = dbo.getUserName(@counter)
  INSERT INTO allUsers (userName) VALUES (@myName)

  IF (@counter < 2995000) BEGIN
    INSERT INTO Users (userName) VALUES (@myName)
  END
  SET @counter = @counter + 1
END

SELECT userName FROM allUsers
WHERE allUsers.userName
NOT IN (SELECT userName FROM Users)
GO

SELECT allUsers.userName
FROM allUsers
LEFT OUTER JOIN Users ON allUsers.userName = Users.userName
WHERE Users.userName IS NULL
GO


Viel Spass beim Nachstellen.

Ciao, Frank

Subqueries / Joins ...

Der folgende Beitrag wurde am 11. 07. 2005, 12:08 Uhr von Frank (no reg) veröffentlicht.

... kurzer Nachtrag ...

es muss natürlich nicht


ALTER FUNCTION


sondern


CREATE FUNCTION


sein.

Ciao, Frank

Subqueries / Joins ...

Der folgende Beitrag wurde am 11. 07. 2005, 19:08 Uhr von Vinzenz Mai veröffentlicht.

Hallo Frank

> in Bezug auf Access kann ich dir das leider nicht sagen, was SQL Server betrifft, sind die Ausführungspläne und damit die Kosten ziemlich ähnlich. Beide verwenden ein Hash-Match, die Outer-Join Variante mit der doppelten verarbeiteten Zeilenmenge plus einem zusätzlichen Filter-Schritt.

Ein interessantes Ergebnis, danke!
Hätte ich nicht gedacht. Aber denken und überprüfen sind zwei Paar Schuhe.


Freundliche Grüße

Vinzenz

Subqueries / Joins ...

Der folgende Beitrag wurde am 11. 07. 2005, 22:54 Uhr von Frank (no reg) veröffentlicht.

N'Abend!

Ja, mich hatte es auch in dem Moment interessiert und mir war grad etwas langweilig :)

Aber ob MS Access _dies_ genauso sieht ... keine Ahnung, da kann ich mir keine Ausführungspläne anzeigen lassen.

Ciao und gut Nacht :)
Frank

Access: Having

Der folgende Beitrag wurde am 11. 07. 2005, 17:05 Uhr von Ilja veröffentlicht.

yo,

> Sowas hört sich immer schrecklich unperformat an (ich weiß nicht, ob dies auch tatsächlich der Fall ist). Das sieht stets so aus, als würde jeder Datensatz aus alleuser mit vielen Datensätzen aus user verglichen wird. Keine Ahnung, was der Optimierer daraus macht.

das sollte bei einem guten dbms eigentlich nicht passieren. die unterabfrage müsste nur einmal ausgeführt werden und das war es dann, da sie unabhängig von der oberen abfrage ist.

Ilja

© 1998-2013 SELFHTMLImpressumSoftware: Classic Forum 3.4