Is it possible to see who voted in polls?

I just tested out polls for the first time in a while, and it works quite well and I like it.

But I would like to have an open poll so we can see who voted for which option. Is this possible? Is there any way to see who voted for what?

You can run the following query to get a list of users who voted and their selected poll options.
Please choose the appropriate query for your Discourse version.

Query for Discourse v2.2.0.beta5 and newer

-- [params]
-- post_id :post_id
-- text :poll_name = poll

SELECT u.id AS user_id, u.username, v.poll_option_id AS option_id, o.html AS option_html
FROM polls p
       JOIN poll_votes v ON (p.id = v.poll_id)
       JOIN poll_options o ON (o.id = v.poll_option_id)
       JOIN users u ON (v.user_id = u.id)
WHERE p.post_id = :post_id AND p.name = :poll_name
ORDER BY u.username, v.poll_option_id

Query for older versions of Discourse up to v2.2.0.beta4

-- [params]
-- post_id :post_id
-- text :poll_name = poll

SELECT votes.user_id, users.username, votes.option_id, options.html AS option_html
FROM (
  SELECT value1 ->> 'id' AS id,
    value1 ->> 'html' AS html
  FROM (
    SELECT json_array_elements(value :: JSON -> :poll_name -> 'options') AS value1
    FROM post_custom_fields
    WHERE post_id = :post_id AND name = 'polls' AND value :: JSON -> :poll_name ->> 'name' = :poll_name
  ) option_values
) options
       JOIN (
  SELECT key :: INTEGER AS user_id,
    trim(json_array_elements(value :: JSON -> :poll_name) :: TEXT, '"') AS option_id
  FROM json_each((
    SELECT value :: JSON
    FROM post_custom_fields
    WHERE post_id = :post_id AND name LIKE 'polls-votes'
  ))
) votes ON (options.id = votes.option_id)
       JOIN users ON (votes.user_id = users.id)
ORDER BY users.username, votes.option_id

How to find post_id

You can use the following query if you need to find the right post_id.

-- [params]
-- topic_id :topic_id
-- int :post_number = 1

SELECT id
FROM posts
WHERE topic_id = :topic_id AND post_number = :post_number

it works! thanks so much. :fireworks:

is there a query for quickly identifying the post ID containing polls? I used the .json URL method but it was surprisingly cumbersome to find the right post within it.

Default values are specified like this:

I updated the query. It’s now a lot simpler. :slight_smile:

Gibt es eine Möglichkeit, die Ergebnisse basierend auf dem Kontenalter zu filtern?

Zum Beispiel, dass ein Konto, das weniger als 60 Tage alt ist, nicht in den Ergebnissen angezeigt wird? Oder gibt es vielleicht eine Möglichkeit, eine Umfrage zu erstellen, die begrenzt, wer basierend auf dem Kontenalter abstimmen kann?

Wir versuchen, möglichen Wahlbetrug durch neu erstellte Konten bei einer bevorstehenden wichtigen Abstimmung zu verhindern.

Das ist ein sehr interessanter Anwendungsfall. Ich finde, wir sollten eine Option haben, um zu verhindern, dass TL0-Nutzer an einer Umfrage abstimmen, @zogstrip!

Gibt es einen Parameter, den ich an die Suchanfrage von @gerhard anfügen könnte, um Benutzer unter einem bestimmten Vertrauenslevel oder Alter nicht in der Abfrage anzuzeigen?

Selbst wenn ich die Stimmen basierend auf den Ergebnissen manuell zusammenzählen müsste, wäre es schneller, als jeden Account manuell auf Alter und deren Stimmen zu überprüfen.

Hier ist eine Abfrage, um ein minimales Vertrauensniveau für die Benutzer festzulegen.

-- [params]
-- post_id :post_id
-- text :poll_name = poll
-- integer :min_trust_level

SELECT u.id AS user_id, u.username, v.poll_option_id AS option_id, o.html AS option_html
FROM polls p
       JOIN poll_votes v ON (p.id = v.poll_id)
       JOIN poll_options o ON (o.id = v.poll_option_id)
       JOIN users u ON (v.user_id = u.id)
WHERE p.post_id = :post_id AND p.name = :poll_name
  AND u.trust_level >= :min_trust_level
ORDER BY u.username, v.poll_option_id

Und hier ist eine Abfrage, um nur Benutzer anzuzeigen, die sich vor einer bestimmten Anzahl von Tagen registriert haben.

-- [params]
-- post_id :post_id
-- text :poll_name = poll
-- integer :days_ago = 30

SELECT u.id AS user_id, u.username, v.poll_option_id AS option_id, o.html AS option_html
FROM polls p
       JOIN poll_votes v ON (p.id = v.poll_id)
       JOIN poll_options o ON (o.id = v.poll_option_id)
       JOIN users u ON (v.user_id = u.id)
WHERE p.post_id = :post_id AND p.name = :poll_name
  AND u.created_at < NOW() - INTERVAL ':days_ago days' 
ORDER BY u.username, v.poll_option_id

Toll :heart_eyes: @gerhard, danke!

Hinweis: Diese Abfrage ist jetzt in den standardmäßig installierten Data Explorer-Abfragen enthalten, sodass Sie diesen Code nicht selbst eingeben müssen!

Eine weitere Möglichkeit, die Post-ID zu finden, insbesondere wenn es sich um den ersten Beitrag handelt, besteht darin, <topic_url>.json anzusehen (z. B. Is it possible to see who voted in polls?). Die Post-ID lässt sich am Anfang dieser JSON-Datei recht leicht finden.

@nbianca könntest du deiner Liste einen neuen Poll-Parameter min_trust_level hinzufügen, der es Poll-Erstellern ermöglicht, festzulegen, wer basierend auf ihrem Vertrauenslevel abstimmen darf?

Die Option sollte in der Poll-Erstellungs-Oberfläche verfügbar sein, und es sollte eine klare Nachricht angezeigt werden, die erklärt, warum bestimmte Benutzer nicht an diesem Poll abstimmen können.

Ihr müsst die Beitrags-ID nicht einmal suchen, da es jetzt für Mitarbeiter einen Export-Button bei Umfragen gibt.

Dies wurde umgesetzt, jedoch etwas anders als angefragt. Umfragen akzeptieren eine Option groups statt min_trust_level, die eine durch Kommas getrennte Liste von Gruppennamen entgegennimmt (z. B. trust_level_2,staff, um TL2+ und alle Mitarbeiter zuzulassen).

Es tut mir leid, aber das ist mir zu verwirrend. Könntest du es mir bitte Schritt für Schritt erklären?