Pattern matching on a stream is probably not a good idea, I'm assuming the number of elements being returned is small enough to fit into memory? You would only work with a stream if it's likely that the elements won't fit in memory, otherwise it's much easier to convert the stream to a list, and then work with the list:
DB.withConnection { implicit c =>
SQL("SELECT value from table1 WHERE externalId = 333")
.map { case Row(value: Option[String]) => value }
.toList
} match {
case Nil => ("notExists", Nil)
case List(None) => ("existsButNull", Nil)
case xs => ("existsWithValue", xs.flatMap(_.toList))
}